我一直在研究org
更多说明和其他文档,我了解发生了什么。
根据NASM 文档 https://www.nasm.us/doc/nasmdoc7.html#section-7.1.1 on the org
指令,缩写origin:
ORG指令的功能是指定NASM在程序加载到内存时假定程序开始的起始地址。 [...] NASM 的 ORG 完全按照指令所述执行:起源。它的唯一功能是指定一个偏移量,该偏移量将添加到该节内的所有内部地址引用中。
因此,NASM编译器假设程序将加载到原始指令指定的地址(即org
)。 BIOS 正是这样做的。根据下列 https://wiki.osdev.org/Boot_Sequence,一旦 BIOS 找到包含有效引导签名的有效引导扇区,引导加载程序将“加载到内存0x0000:0x7c00处(段0,地址0x7c00)."
从上面的引用来看,当 NASM 文档说“内部地址引用”时,它指的是对代码中使用的具体内存区域的所有引用(例如引用标签等)。例如,上面的引导加载程序代码中的行:mov si, bootmsg
将解决bootmsg
to 0x07c00 + offset
,其中偏移量由字符串的第一个字节的位置确定bootmsg
(即“W”)。
使用上面的代码,如果我使用以下命令反汇编 bin 文件ndisasm实用程序 https://www.nasm.us/doc/nasmdoca.html我看到以下内容:
00000000 EB2C jmp short 0x2e
00000002 57
00000003 656C
00000005 636F6D
00000008 6520746F
0000000C 206D79
0000000F 204F70
00000012 657261
00000015 7469
00000017 6E
00000018 67205379
0000001C 7374
0000001E 656D
00000020 2100
00000022 AC lodsb
00000023 08C0 or al,al
00000025 7406 jz 0x2d
00000027 B40E mov ah,0xe
00000029 CD10 int 0x10
0000002B EBF5 jmp short 0x22
0000002D C3 ret
0000002E 31C0 xor ax,ax
00000030 8ED8 mov ds,ax
00000032 8EC0 mov es,ax
00000034 BE027C mov si,0x7c02
00000037 E8E8FF call 0x22
0000003A FA cli
0000003B F4 hlt
00000... ... ...
(我删除了从0x00000002到0x00000020生成的指令,因为那是我的bootmsg
字符串,代表数据,而不是代码)。
正如我们从输出汇编中看到的,在地址 0x00000034 处,我的bootmsg
已替换为 0x7c02(例如 0x7c00 + 偏移量=0x02)。
迈克尔·佩奇 https://stackoverflow.com/questions/54045259/setting-segment-registers-after-org-instruction?noredirect=1#comment94930637_54045259也提供了一些非常扎实的见解。认为引导加载程序加载到 0x7c0:0x0000(段 0x07c0,偏移量 0)是一种常见的误解。尽管从技术上讲可以使用这一点,但它已被标准化为使用零段偏移量(一个好的做法是在引导扇区的最开始处强制执行 CS:IP https://wiki.osdev.org/Boot_Sequence)。正如 Michael 所提到的,如果需要更多信息,请查看以下第 4 节段偏移寻址指南 https://thestarman.pcministry.com/asm/debug/Segments.html.