boot.asm为什么要使用org汇编指令
问题
boot.asm编译之后,存放于软盘映像的第一个扇区。BIOS会自动将其加载至0x7c00处,然后跳转至0x7c00开始执行代码。那么,为什么要使用org指令指定编译器从0x7c00开始编址呢?
分析
首先要明确,编址是什么意思?对于一条指令,如果其中不含有符号,则不存在编址问题。例如mov ax,0x100,编译之后就是一串机器码,在二进制文件中依次排列即可,不需要编址。所以,所谓“编址”这个概念,是针对含有符号的指令。例如jmp
short LABEL_START,例如call DispStr, 例如add
ax,BootMessage。下面对这三种指令一一分析。
jmp分为三种。jmp near、jmp near、jmp far。对于前两种,在机器码中,实际存放的是jmp的下一条指令到目标指令的间隔距离。这个距离是不受org指令指定的编址数值影响的。对于jmp
far,需要具体到上下文讨论。详细的论述见http://www.cnblogs.com/mfm11111/archive/2009/03/27/1422828.html。
call除了不能实现short转移外,原理与jmp基本相同。可以参考
http://www.cnblogs.com/mfm11111/archive/2009/03/29/1424300.html。
add ax,BootMessage
......
BootMessage:
db "Booting.............."
这段汇编代码中,BootMessage指向一串字符,在编译的时候BootMessage这个符号常量会被替换成具体的数值。这个数值,就完全受到org指令指定的编址地址控制。BootMessage=org指定数值+BootMessage指向的内存在整个汇编代码中的偏移。
总结
现在,我们就明白了文章开头提出的问题。如果不使用org 0x7c00,则默认为从0x0100开始编址。假设BootMessage指向的内存偏移是0x00f0,则BootMessage就会被替换为0x0100+0x00f0=0x01f0。而实际上,BIOS将启动扇区加载到0x7c00之后,db
"Booting......."这个字符串是被写到了内存0x7c00+0x00f0=0x7cf0处。而系统尝试读取的地址却是0x01f0,这个地址是完全错误的。
总之,Org指令表示下一行汇编代码在汇编成机器指令时,第一条指令从Org后指定的地址开始存放