最近我正在学习如何编写启动扇区,这是我正在学习的完整代码:
org 07c00h
mov ax, cs
mov ds, ax
mov es, ax
call DispStr
jmp $
DispStr:
mov ax, BootMessage
mov bp, ax
mov cx, 16
mov ax, 01301h
mov bx, 000ch
mov dl, 0
int 10h
ret
BootMessage: db "Hello, OS!"
times 510-($-$$) db 0
dw 0xaa55
如果您知道如何启动系统,那么这是一个非常简单的代码。结果是屏幕上显示一行Hello OS!
,我唯一不知道的是第一行:org 07c00h
,书中告诉我代码行让编译器找到地址到7c00h的位置,但解释非常模糊,我真的不知道它在这里使用它。线org 07c00h
在这里做什么?我试图删除该行,并使用nasm创建一个bin
文件,然后使用bochs来启动bin文件。与前一个没什么不同:“你好OS!”也显示在屏幕上。我可以说第一行在这里什么都不做?什么是使用org xxxx
在世界?
答案 0 :(得分:3)
这是您在一个步骤中拥有汇编程序和链接程序的地方。组织告诉汇编器告诉链接器(在这些情况下通常是相同的程序)在物理内存空间中放置后面的代码。当您使用C编译器或其他高级语言编译器时,您通常会有单独的编译和链接步骤(尽管编译器通常会在幕后为您调用链接器)。源被编译为与位置无关的目标文件,其中一些指令未实现等待链接步骤。链接器从描述内存空间的用户获取对象和链接描述文件或信息,然后从那里编码该内存空间的指令。
User786653设置得非常好,它告诉汇编程序它不能自己弄清楚这些指令将要存在的内存空间/地址,以防需要在指令中进行位置相关编码。如果它是包含地址信息的二进制文件,它也会在输出二进制文件中使用该信息,例如elf,srec,ihex等。
答案 1 :(得分:3)
汇编程序正在将您的代码的每一行转换为处理器指令,并依次生成这些指令到输出二进制文件中。这样做,他维护一个内部计数器,从0和更高的位置开始计算任何此类指令的当前地址。
如果你正在组装一个普通的程序,这些指令将最终出现在某个目标文件的代码部分,只有空白的地址槽,之后必须由链接器填入适当的地址,所以它不是问题
但是当您组装一个没有任何部分,重定位和其他格式的平面二进制文件时,只需要原始机器指令,那么汇编程序就没有关于标签指示位置和数据地址的信息。因此,例如,当您有一条指令mov si, someLabel
时,汇编程序只能从二进制文件开头的0开始计算该标签的偏移量。也就是说,它假定您的代码将从代码段中的偏移量0开始位于内存中。
如果不是这样,并且您希望内存中的机器指令从其他地址开始,例如。 7C00
,然后您需要通过在源代码的开头写7C00
告诉汇编程序您的程序的起始地址为org 0x7C00
。该指令告诉汇编器它应该从7C00
而不是0
启动其内部地址计数器。结果是,此类程序中使用的所有地址都将移位7C00
。汇编程序只需将7C00
添加到为每个标签计算的每个地址。效果就好像标签位于地址的内存中,比如7C48
(7C00 + 48
),而不仅仅是0048
(0000 + 48
),无论它是什么从二进制图像文件的开头只偏移48个字节(在偏移量7C00
加载后将给出正确的地址)。
关于您的其他问题:7C00
是引导加载程序的物理地址。您可以用不同的方式将此物理地址表示为逻辑地址(段:偏移量),因为段重叠(下一段在前一段之后开始16字节(十六进制为10
))。例如,您可以使用最简单配置的逻辑地址0000:7C00
:从RAM的开头开始使用段0
,并从7C00
偏移0
。或者,您可以使用逻辑地址07C0:0000
,即7C0
段。请记住,段彼此间隔16个字节?因此,您只需将此7C0
乘以10
(十进制为16
)即可获得7C00
- 请参阅?这是在十六进制地址中向右移位一个位置的问题! :-)现在你只需添加你的偏移量,这次是0
,所以它实际上仍然是7C00
。段0
中的字节07C0
,从内存中的7C00
开始。
当然,您也可以使用更复杂的地址,例如0234:58C0
,这意味着该段从2340
开始,当您向其添加58C0
偏移时,再次得到7C00
:-)但这样做可能会令人困惑。这一切都取决于您需要什么配置。如果您想将7C00
物理地址视为细分的开头,只需使用细分07C0
,您的第一条指令将位于偏移0
,因此您无需放置org
指令,或者你可以放org 0
。但是如果你需要读取/写入7C00
地址以下的一些数据(例如,查看BIOS数据或摆弄中断向量),那么使用段0
和偏移7C00
这意味着您的第一条指令(二进制文件中的第0个字节)将位于内存中的7C00
物理地址;然后你必须从上述原因添加org 0x7C00
指令。