我开始了编写玩具操作系统的旅程,并且正在寻找资源和书籍来帮助我。
我一直无法弄清楚的一项功能是网络。我能找到的所有关于 x86 程序集中网络的教程都是基于 Unix/Linux 网络系统调用的。
如何在裸机 x86 组装中完成它?
我写了一个小bootloader用于学习目的,它会打印出bootloader第一条指令的内存地址,肯定是0x7c00。看下面的汇编源代码运行良好。
boot.s
.code16
.global init
init:
mov $0x07c0, %ax
mov %ax, %ds
mov $0x07e0, %ax
mov %ax, %ss
mov $0x2000, %sp
call next
next:
pop %bx
sub $(next-init), %bx # starting point of memory address, now stored in %bx
call print_register
jmp .
print_register: # always print out value in %bx
mov %bh, %cl
shr $0x4, %cl
and $0x0f, %cl
call print_digit
mov %bh, %cl
and $0x0f, %cl
call print_digit
mov %bl, %cl
shr $0x4, %cl
and $0x0f, %cl
call …Run Code Online (Sandbox Code Playgroud) 需要6个字节来存储中断门描述符,每个描述符由32位段选择器和16位偏移量组成。中断描述符表的大小(以字节为单位)是多少?
第一:这个问题在这里有重复:
像 Windows 或 Linux 这样的现代操作系统如何知道芯片组特定的内存映射?
但是这个问题的答案是关于设备树和ACPI(对于旧式PC),没有详细信息我需要编写汇编或C代码来利用ACPI表中的信息,我现在尝试首先了解旧式PC以及如何为了解码 ACPI 的表,我尝试进行一些搜索,发现最重要的表是 DSDT ,现在我的问题是如何解码表中的信息以获取详细的内存映射(范围)并获取哪些设备连接到CPU,如何获取内存中DSDT的地址? ,我尝试进行一些搜索,但我无法理解我认为与该主题相关的 AML 语言。如果有人详细说明并提供了解 ACPI 表并为初学者解码它们的良好材料,我将很有帮助,问题是对我来说,我无法记住标准的固定内存映射,因为我想知道相同的操作系统版本如何在不同的芯片组上运行,必须有一种动态方法来检测整个映射,因此获取整个映射的建议过程是还有我的另一个问题
另请注意,这是我学习如何直接与裸机硬件设备单独通信的第一步(这是第二步)
谢谢
我有一个带有时钟中断的简单工作(32 位保护模式)内核。我可以看到这个中断正在工作,因为它多次打印 \xc2\xab\xc2\xa0clock\xc2\xa0\xc2\xbb 。我还可以看到这个中断将控制权交还给内核,因为它在几次时钟中断后在屏幕上打印 \xc2\xab\xc2\xa0Kernel has stop\xc2\xa0\xc2\xbb ,就像它应该的那样。中断与内核位于同一代码段中。
\n我没有设置任何 TSS,但它正在工作。我可以在这篇文章( https://web.archive.org/web/20160326062442/http://jamesmolloy.co.uk/tutorial_html/10.-User%20Mode.html )上读到,当发生中断时,CPU将查看选定的 TSS 段以更新寄存器。
\n如果我没有\xe2\x80\x99t 有这个 TSS ,它如何工作?是因为当中断发生时CPU仍然会自动推送EIP、CS、EFLAGS、EPS、SS并在iret上恢复它们吗?
\n如果我加载单个 TSS,该中断如何知道它应该使用该 TSS?使用ltr指令将在GDT内获取相应的tss段?
\n并不是真正相关,但是当使用硬件上下文切换并跳转到一个 TSS 时,它会在返回时自动跳转到上一个(没有下一个字段,所以 I\xe2\x80\x99m 有点丢失)tss 段吗?
\n这些问题我无法从我的学校课程、osdev 或这个论坛中真正得到明确的答案。
\n在函数中outb(0x3D5, (uint8_t) (pos & 0xFF));,我无法理解按位运算的目的。pos是一个uint16_t变量。
&仅 8 位 1 的按位运算的目的是什么。该&操作只是将该值与 8 位 1 进行比较,据我所知,这只会产生相同的值。这个操作如何改变pos的值?
作为背景,如果它很重要,则该函数outb旨在将右侧参数的值移动到由端口(左侧参数)索引的寄存器中。在本例中,pos是 VGA 适配器内存中的位置。该函数outb使用内联汇编和汇编指令out。
我知道这个问题被问了很多,但我找到的每个答案都不适合我。我正在尝试加载stage 2位于图像文件第二个扇区的操作系统(0x200)
这是我尝试使用的代码:
bits 16 ; Starting at 16 bits
org 0x0 ; And starting at 0
jmp main ; Hop to main!
; TODO: copy comment from prev. loader
; args: SI
print:
lodsb ; Load the next/first character to AL
or al, al ; Is it 0?
jz donePrint ; Yes - Done.
mov ah, 0eh ; No - keep going.
int 10h ; Print character.
jmp print ; Repeat
donePrint:
ret ; Return …Run Code Online (Sandbox Code Playgroud) 我正在尝试开发一个引导加载程序。但有一个部分我不明白。我知道当我的汇编文件中定义了 ORG 7C00 时,程序将加载到磁盘 7C00 上。我将其编译为二进制文件并在 Magic ISO 中创建了 iso 文件。然后,当我查看 ISO 文件的十六进制版本时,我看到我编写的代码是从 D800 地址开始的。不是应该安装在7C00吗?
org 0x7C00
bits 16
start:
cli
times 510 - ($ - $$) db 0
dw 0xAA55
Run Code Online (Sandbox Code Playgroud)
https://i.stack.imgur.com/TFVDE.png
我还有另一个问题。地址 D010 处还有另一个引导加载程序签名。为什么?
https://i.stack.imgur.com/dyZgl.png
另外,我还想知道一件事。我想将一些文件放入我的 ISO 文件中,并且想在此级别读取这些文件。我在 VirtualBox 中进行实验。如何读取 ISO 文件中的文件。或者我如何运行一个程序。所以我想做的就是将内核放置在这里并从引导加载程序加载它。
如果我错了,是否有资源详细说明如何加载引导加载程序以及如何加载 BIOS?
我正在制作一个运行 Snake 的操作系统,并且我处于 32 位保护模式,但我无法在屏幕上绘制像素。我在实模式下切换到模式 0x13 (320x200x256),屏幕一片空白。进入保护模式后,内核运行并且我正在绘制的像素不会出现。
我从这篇OSDev 文章中汲取灵感,该文章切换到保护模式并将像素绘制到视频显示上。
这是kernel.c
#include "display.h" // Include Display Drivers
#include "constants.h" // Include constants that C doesn't have included
#include "keyboard.h" // Include the custom keyboard driver
void _start(){} // Remove LD Warning
DisplayDetails globalDisplayDetails; // The display details.
int main(){
// Init the display details
DisplayDetails details = display_init();
globalDisplayDetails = details;
bool running = true;
while(running){
// This is the OS loop
putpixel(100, 100, 0x00FFFFFF);
} …Run Code Online (Sandbox Code Playgroud) 我目前正在遵循启用GDT细分的指南.我正在使用GNU Assembler和Bochs进行仿真.
我知道我需要使用GDT描述符加载GDT寄存器.我已经完成了,接下来的步骤是将所有具有相对于GDT的偏移的段寄存器加载到代码/数据段描述符的各个位置.这样做的代码如下:
reloadSegments:
; Reload CS register containing code selector:
JMP 0x08:reload_CS ; 0x08 points at the new code selector
.reload_CS:
; Reload data segment registers:
MOV AX, 0x10 ; 0x10 points at the new data selector
MOV DS, AX
MOV ES, AX
MOV FS, AX
MOV GS, AX
MOV SS, AX
RET
Run Code Online (Sandbox Code Playgroud)
但是,我无法理解如何可以隐式加载具有偏移量的CS寄存器,而不会显着跳跃到CS:IP对指向的任何内存位置 - 即,如果代码段描述符位于GDT_start + 0x10,我尝试将0x10加载到CS寄存器,虚拟机跳转到0x10:IP,我从不输入.reload_CS标签.
我的例程版本(at&t语法):
_start:
// Disable interrupts
cli
// Load GDT register with location of GDT
lgdt 0x3c
// Load location of Code …Run Code Online (Sandbox Code Playgroud) osdev ×10
assembly ×7
x86 ×7
bootloader ×3
nasm ×3
c ×2
kernel ×2
acpi ×1
bare-metal ×1
gcc ×1
interrupt ×1
iso-image ×1
networking ×1
x86-16 ×1