什么是在组装中使用“org xxxx”

时间:2012-04-24 15:51:07

标签: assembly operating-system x86 boot pc

最近我正在学习如何编写启动扇区,这是我正在学习的完整代码:

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在世界?

2 个答案:

答案 0 :(得分:3)

这是您在一个步骤中拥有汇编程序和链接程序的地方。组织告诉汇编器告诉链接器(在这些情况下通常是相同的程序)在物理内存空间中放置后面的代码。当您使用C编译器或其他高级语言编译器时,您通常会有单独的编译和链接步骤(尽管编译器通常会在幕后为您调用链接器)。源被编译为与位置无关的目标文件,其中一些指令未实现等待链接步骤。链接器从描述内存空间的用户获取对象和链接描述文件或信息,然后从那里编码该内存空间的指令。

User786653设置得非常好,它告诉汇编程序它不能自己弄清楚这些指令将要存在的内存空间/地址,以防需要在指令中进行位置相关编码。如果它是包含地址信息的二进制文件,它也会在输出二进制文件中使用该信息,例如elf,srec,ihex等。

答案 1 :(得分:3)

汇编程序正在将您的代码的每一行转换为处理器指令,并依次生成这些指令到输出二进制文件中。这样做,他维护一个内部计数器,从0和更高的位置开始计算任何此类指令的当前地址。

如果你正在组装一个普通的程序,这些指令将最终出现在某个目标文件的代码部分,只有空白的地址槽,之后必须由链接器填入适当的地址,所以它不是问题

但是当您组装一个没有任何部分,重定位和其他格式的平面二进制文件时,只需要原始机器指令,那么汇编程序就没有关于标签指示位置和数据地址的信息。因此,例如,当您有一条指令mov si, someLabel时,汇编程序只能从二进制文件开头的0开始计算该标签的偏移量。也就是说,它假定您的代码将从代码段中的偏移量0开始位于内存中。

如果不是这样,并且您希望内存中的机器指令从其他地址开始,例如。 7C00,然后您需要通过在源代码的开头写7C00告诉汇编程序您的程序的起始地址为org 0x7C00。该指令告诉汇编器它应该从7C00而不是0启动其内部地址计数器。结果是,此类程序中使用的所有地址都将移位7C00。汇编程序只需将7C00添加到为每个标签计算的每个地址。效果就好像标签位于地址的内存中,比如7C487C00 + 48),而不仅仅是00480000 + 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指令。