学习笔记
使用教材(配书源码以及使用方法)
《一个64位操作系统的设计与实现》
http://www.ituring.com.cn/book/2450
https://www.jianshu.com/p/28f9713a9171
参考资料
org 指令的作用其实是 影响标号label的值Setting segment registers after ORG instruction
https://stackoverflow.com/questions/54045259/setting-segment-registers-after-org-instruction
如果你的代码中有一个标号叫做bootmsg,它的值是
samll offset
:
- 在
org 0
的时候,这个标号的值被解读成0x0000+samll offset
;- 在
org 0x7c00
时,这个标号的值被解读成0x7c00+samll offset
- 这个
samll offset
其实就是标号所在处距离代码开始处的代码字节数
org 到底影响了谁?
- 第一,
org
指令影响的是 标号的绝对地址 - 第二,
org
指令不会影响寄存器,说白了,不会影响CS 、DS、ES、SS
为什么org
后面要加个0x7c00
?
- 这个问题的本质是问为什么值是
0x7c00
,不是0x0000
,或者0x1234
,也不是0xABCD
阮一峰:为什么主引导记录的内存地址是0x7C00?
http://www.ruanyifeng.com/blog/2015/09/0x7c00.html
容易混淆的概念
-
首先,无论你的汇编代码头部加不加一句
org 0x ★♂☆◆
指令,你的主引导扇区代码都会被BIOS 自动加载到内存的0x0000:7C00
处,自动加载这是焊死在硬件上面的规范,说白了,自动加载与org
指令半点关系都没有; -
其次,是不是主引导扇区代码,看的是你扇区最后两个字节是不是
0x55aa
,也和org
指令没有半点关系; -
然后,有些主引导扇区汇编代码不加org指令也可以正常运行,就是因为那些代码里面没有涉及到 标号label 相关的代码,不需要对 标号label 进行绝对地址的计算
[举例]下面这就是没有使用label也没有使用org指令的主引导扇区代码
https://www.jianshu.com/p/207aaf0f986b
-
接着,标号是标号,标号不是寄存器,标号是程序员可以自由任意随便取名字的,取的那个名字只是帮助你阅读代码用的,在代码经过汇编编译器之后标号会被解读成一个具体的数值,
org
影响的就是最后算标号的那个具体数值; -
最后,这个标号代码的那个具体的数值是什么?
是一个offset
,即当前标号所在代码行距离代码开始处的字节数
为什么需要 org 指令?
-
假设,你的标号距离你的代码开始处是
八个字节
,那个标号的值原本应该就是0x08
的,这个原本可以是不写org指令
,也可以是写个org 0x0000
,反正无论哪种这时标号会被解读成数值0x00000008
; -
由于你是主引导扇区的代码,你的代码被自动加载到内存
0x0000:7C00
处了,代码被加载到内存,实际上是说机器码被加载到内存,也就说是说无论你的代码被加载到0x0000:7C00
还是被加载到0x1234:5678
这里, 数值0x00000008
还是数值0x00000008
; -
那么问题就来了?
数值0x00000008
是一个绝对地址,你现在代码全部在0x0000:7C00
,你真正想要找的标号是被放到了从0x0000:7C00
开始后的八个字节的地方,它应该是0x00007C000+0x00000008 = 0x00007C08
而不是0x00000008
-
那么如何解决?
[1] 要么直接修改标号的绝对地址,在使用标号赋值的时候,
强制加上0x7c00
,比如mov ax,bootmsg
写成mov ax,bootmsg+0x7C00
;
[2] 要么,在代码开头使用org 0x7C00
,代码还是写mov ax ,bootmsg
但是它会悄悄地把bootmsg解读成bootmsg+0x7C00
如何验证猜想
- [OS64位][004]调试源码:使用工具 nasm 、bochs 验证 org 0x7c00 对标号StartBootMessage 最终数值的影响
网友评论