关于引导程序第一条指令为什么是org 07c00h,org到底是干嘛的

来源:互联网 发布:亚马逊卖家网络ip 编辑:程序博客网 时间:2024/05/16 10:19

    ​费解了好久,一直不明白org是干嘛的。首先平时编程绝对不加org也能运行,为什么写引导区就要加上呢。其次,很多文章对此的解释是,org 07c00h会把程序加载到内存地址07c00(0000::7c00)处,但是它真能决定程序加载位置吗?

    ​先说第二个问题,在BIOS自检等一系列工作完成后,要开始引导了。计算机会将硬盘0面0道1扇区512字节加载到07c00h(0000::7c00)处。不管有没有org,都会加载到07c00处。org根本对程序加载位置没有任何影响,它只是伪指令,只在汇编器汇编阶段起作用,之后不翻译成机器指令。那既然程序已经加载到了07c00h处,为什么需要org??因为org是对汇编器的指示性语句。

我们假设程序代码如下(这程序过于简陋,只是为了示例!):

code segment  start:mov ax,offset msg    msg db "hello"code endsend start

    ​如果程序这么写的话,那么汇编器默认在汇编时将mov ax,offset msg汇编成mov ax,0003h(这条语句3字节长,那么msg在段内偏移就是0003h了)。正常情况下,系统把这个程序会自动加载到自由内存区,并且是加载到某一段的0000h偏移处。比如在我的电脑上debug可以看到


程序被加载到了075B段,偏移0000h处。

注意!我们的msg db "hello"被当作指令汇编了,显出来是push 6c65,其实push 6c65是我们的字符串!!

看看内存里的情况就知道了



看到了吧,

    好,回归正题,程序被加载到了075B段,偏移0000h,如果以后需要使用msg字符串,那么ax里面的偏移地址0003h是正确的,075B:0003处确实是我们的字符串。


    ​假设这个程序由于某种原因被系统强制加载到了075B:0100h,那么msg地址变成了075B:0103h,就是在0100h上加上自己的代码段段内偏移0003h。但是,mov ax,offset msg依然被汇编成了mov ax,0003h,以后要用字符串时,就去075B:0003处找,显然我们的程序字符串地址为075B:0103h,但是根据ax值,却要去075B:0003找字符串,肯定找不到。


    ​那么怎么办呢,org xxxx指令就派上用场了。告诉汇编器,把所有对内存的地址引用全都加上xxxx。

所以假设我们的程序被系统强制加载到了075B:0100h。

没关系,源代码改为:

code segment    org 0100h    start:mov ax,offset msg    msg db "hello"code endsend start

反汇编如下



    ​果然,内存引用地址从0003被加上0100,变成0103了。现在程序要去找msg,就用ax的值去075B:0103h找。而实际上,075B:0103h处正好是字符串hello。这样就找对了。

    ​从此我们可以看出,org对程序加载位置没有任何影响。他只是告诉汇编器,给内存引用全部加上一个值,这在程序被强制加载到非0000h偏移时很有用。

    ​回到第一个问题,为什么一般程序不加org也对,因为程序被默认加载到某个内存段内,偏移0000的位置,不加org,相当于所有内存引用都以自己段内的偏移为准(msg在自己的代码段偏移0003),那么某个变量或标号在自己代码段内的偏移就是在内存段内的偏移。


    ​所以,一般编程不加org,因为程序默认加载地址的偏移就是0000h,可写引导扇区时,程序会被加载到0000段,偏移7c00,偏移不是0000,所以用org让所有的内存引用全都加上7c00h。于是,在引导扇区程序里,我们开头会看到这么一句 org 7c00h,因为汇编里十六进制要以数字开头,所以应该这么写org 07c00h。


    ​至此,我想说的说完了,可能讲的有点乱,不过这问题实在是当初让我非常晕,在大多数材料不深究的情况下,我随便写写,为自己记下笔记,也希望能对一些同样迷惑的朋友有指导作用。

    ​欢迎指正!

0 0
原创粉丝点击