汇编语言中的ORG问题:只有彻底搞清楚了ORG的原理,你才能在汇编语言和操作系统开发中游刃有余。
ORG的作用不是指定程序的放置位置,它没有那样的功能和能力!这点,对于做过单片机项目的人来说,特别容易上当。如在程序的开头放上一句:ORG 500H,代表的含义并不是指程序是就从内存500H的地方开始放。ORG语句是否需要、ORG语句后面的数值应该是多少,并不是写程序的人主观指定的,而是被动指定的!
(i) 什么情况下不需要ORG?
<1> 不涉及从内存取数据的时候,程序不需要ORG。ORG有无不影响程序指令的顺序执行,也即不影响CS、IP等值。ORG的影响往往只是针对DS、ES等来说的。
<2> 程序没有被强制指定存放位置的时候(默认在段的0偏移地址开始放置程序),程序不需要ORG。
(ii) 什么情况下需要ORG?
当程序被强制指定存放位置的时候,必须要有ORG。
典型的以下两种场景:
<1>DOS下面的.com程序,由于程序被强制指定了只能放在段内PSP之后且在100H的地方,因此程序必须要用ORG。如果不用ORG 100H指令,当访问低端内存地址的时候(如MOV AX,[02H])就一定会错误的访问到PSP里面的数据了。而用了ORG 100H指令之后,以上语句,就能访问到正确的内存地址:100H+02H。
关于这块知识,我认为经典的教程在这个地方:
https://blog.youkuaiyun.com/ruyanhai/article/details/7177904
<2>系统引导扇区程序:由于计算机强制指定了只能放在7C00H的内存地址,因此程序必须要用ORG。如果不用ORG 7C00H,那么语句MOV AX,[02H],访问到的内存地址也将是错误的地址02H,而用了ORG 7C00H之后,访问到的内存地址就是正确的地址: 7C00H+02H。
关于这块知识,我认为经典的教程在这个地方:
https://blog.youkuaiyun.com/daiyutage/article/details/8918290
(iii) 为什么需要ORG?
我们写汇编程序的时候,程序最终以.COM或.EXE或.BIN等形式放在计算机的内存什么位置是无法预知的。那么在编译阶段,如果程序需要从内存取数据进行操作,也就无从预知实际的物理地址,那么程序是不是就没有办法运行了呢?为了解决这个问题,编译原理只能将程序中的内存位置定义成相对位置,也即任何对内存地址的定位都翻译成离程序最开始的偏移量。这样,无论最终的程序从内存什么地方开始放,都不会影响程序的正确运行:
可见,程序无论放在什么位置,只需要将相对偏移量+程序放置位置,就能得到准确的物理位置。而这个累加计算工作,就是计算机在将程序装载到内存的时候,产生二进制BIN格式过程中要完成的工作,最终得以保证程序正确运行。我们知道相对偏移量在编译阶段由编译器产生,那么程序放置位置由谁产生呢?无疑,就只有ORG。
(iv) ORG应该怎么取值?
显然,程序从哪个地方开始放置,就应该取多少值。因此,对.COM来说,程序是从100H的地方开始,ORG就只能取100H。引导扇区是从7C00H的地方开始,ORG也就应该取7C00H。只有这样取值,计算机才能在最终的程序中准确定位变量在内存中的物理位置。
(v) 如何避免使用ORG?
实际上,你可以看到并不是所有的汇编程序都一定需要ORG。比如引导扇区程序,如果我们自定义了DS和ES的值,就不再需要在程序的开头加上ORG 7C00H。但是这个DS和ES的值必须要有严格的值,使得程序相对DS和ES来说,刚好是从0偏移位置开始放置才行。
MOV AX, 7C0H
MOV DS, AX
MO