关于引导程序第一条指令为什么是org 07c00h,org到底是干嘛的
2014-06-10 21:45
260 查看
费解了好久,一直不明白org是干嘛的。首先平时编程绝对不加org也能运行,为什么写引导区就要加上呢。其次,很多文章对此的解释是,org 07c00h会把程序加载到内存地址07c00(0000::7c00)处,但是它真能决定程序加载位置吗?
先说第二个问题,在BIOS自检等一系列工作完成后,要开始引导了。计算机会将硬盘0面0道1扇区512字节加载到07c00h(0000::7c00)处。不管有没有org,都会加载到07c00处。org根本对程序加载位置没有任何影响,它只是伪指令,只在汇编器汇编阶段起作用,之后不翻译成机器指令。那既然程序已经加载到了07c00h处,为什么需要org??因为org是对汇编器的指示性语句。
我们假设程序代码如下(这程序过于简陋,只是为了示例!):
程序被加载到了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。
没关系,源代码改为:
果然,内存引用地址从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。
至此,我想说的说完了,可能讲的有点乱,不过这问题实在是当初让我非常晕,在大多数材料不深究的情况下,我随便写写,为自己记下笔记,也希望能对一些同样迷惑的朋友有指导作用。
欢迎指正!
先说第二个问题,在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 ends end 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 ends end 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。
至此,我想说的说完了,可能讲的有点乱,不过这问题实在是当初让我非常晕,在大多数材料不深究的情况下,我随便写写,为自己记下笔记,也希望能对一些同样迷惑的朋友有指导作用。
欢迎指正!
相关文章推荐
- 关于引导程序第一条指令为什么是org 07c00h,org到底是干嘛的
- 关于引导程序第一条指令为什么是org 07c00h,org到底是干嘛的
- 引导程序为什么要org 07c00h
- 关于Microsoft Visual Studio .NET 2003 引导程序插件
- 【转帖】关于修复win7/vista 引导程序
- 关于androidstuio运行程序遇到 Error:(11, 8) 错误: 无法访问HttpEntity 找不到org.apache.http.HttpEntity的类文件解决方法
- 转行解惑0--程序为什么能完成指令
- 做个网站,建站公司不给你程序源码,没法做SEO,到底是为什么?
- 关于asp.net web程序的访问,为什么老提示输入用户名和密码?
- 程序运行地址和加载地址-为什么使用位置无关指令
- 关于Timer使用,为什么程序会死掉
- linux引导程序为什么要把自己加载到内存的7c00h这个特定的地方?
- >>关于.NET程序为什么在最小化的时候变得很小的问题
- opencv关于视频添加滚动条的问题 一样的程序 为什么结构不一样呢!奇怪极了(4)
- 关于指令、数据、程序和进程的一些思考
- 嵌入式linux应用开发完全手册 关于pc为什么指向下两条指令的位置问题
- BIOS选择07c00h加载引导程序的解释
- 为什么dos下的com文件都要org 0100h呢?为什么系统启动时要org 07c00h呢
- 关于ARM跳转指令b跳转指令范围为什么为正负32M??
- linux引导程序为什么要把自己加载到内存的7c00h这个特定的地方?