000. 这里存放一些疑惑和解答

1. org 0x7c00

   ORG:  是伪指令, 而且是给链接器用的, 是在链接的时候,  让 代码里的所有偏移地址, 从  0x7c00开始, 而不是  0x0000

   比如  mov ds, ax,默认编译完成后 , 他的地址是  从 0x00开始, 逐渐递增,  而  org ***, 只是让 地址从  0x**开始递增而已.

   一些其他的书籍(比如自己动手写操作系统), 很多示例代码, 会在boot.s先加上  org 0x7c00;

  原因是,  bios会做一些固定的操作, 自检完毕后, 会把  启动扇区的头512个字节加载到  0x0000:  0x7cc 处,

并且设置  cs = 0x0000, ip = 0x7c00. 这里要说明一下,  如果,  boot.s里全是  mov ds, ax这种不在乎偏移地址的操作, 其实没啥大关系, 一点儿影响都没有, 因为 不论  boot.s 有没有 org 0x7c00, 反正 可执行代码都被加载到了 0x7c00出, 一样可以执行的.

至于为什么一定要加 org, 是因为, 程序中, 会用某些  label 

比如 

mov ax, msg

msg:

    .ascii  "hello system"

如果没有 org , 那么实际上,编译后的 , 是这种的,  mov ax  0x12;  0x12 是 msg的地址, 当加了  org 0x7c00的时候,  编译后是  mov ax, 0x7c12, 这才是  msg真正的地址, ORG只是起了这个作用而已.

在 linux 0.00 那个多任务的示例代码中, 没有用这种方式(貌似是 nasm独有的? 不知道), 用了 jmpi  go, 0x7c0, 这种方式, 实际上是通过改变段寄存器CS来达到这种效果的

cs= 0x7c0, ip = go, 所以加完了, 也是 0x7c0 左移四位(*16), 再加上go,一样是  0x7c00 + go.

2.  汇编指令IRET


【指令格式】IRET

【指令功能】IRET(interrupt return)中断返回,中断服务程序的最后一条指令。IRET指令将推入堆栈的段地址和偏移地址弹出,使程序返回到原来发生中断的地方。其作用是从中断中恢复中断前的状态,具体作用有如下三点:

1.恢复IP(instruction pointer):(IP)←((SP)+1:(SP)),(SP)←(SP)+2

2.恢复CS(code segment):(CS)←((SP)+1:(SP)),(SP)←(SP)+2

3.恢复中断前的PSW(program status word),即恢复中断前的标志寄存器的状态。
(FR)←((SP)+1:(SP)),(SP)←(SP)+2

4.恢复ESP(返回权限发生变化)

5.恢复SS(返回权限发生变化)

以上操作按顺序进行。

3. CALL和 RET指令

ret指令和retf指令

ret指令用栈中的数据,修改IP的内容,从而实现近转移
retf指令用栈的数据,修改CS和IP的内容,从而实现远转移

CPU执行ret指令时,相当于进行:

pop IP

CPU执行retf指令时,相当于进行:

pop IP
pop CS

call指令
当执行call指令时,进行两步操作:
1)将当前的IP或CS和IP压入栈中
2)转移

call指令不能实现短转移,它的书写格式同jmp指令

依据标号进行转移的call指令
语法格式:call 标号
汇编解释:(1) push IP (2) jmp near ptr 标号

依据目的地址在指令中的call指令
语法格式:call far ptr 标号
汇编解释:(1) push CS (2) push IP (3) jmp far ptr 标号

转移地址在寄存器中的call指令
语法格式:call 16位reg
汇编解释:(1) push IP (2) jmp 16位reg

转移地址在内存中的call指令
语法格式一:call word ptr 内存单元地址
汇编解释一:(1) push IP (2) jmp word ptr 内存单元地址

语法格式二:call dword ptr 内存单元地址
汇编解释二:(1) push CS (2) push IP (3) jmp dword ptr 内存单元地址
也就是说,  CALL 会 自动把 IP或者CS / IP压入栈中  ,然后再 JMP, 

而JMP,就只是设置了cs:ip(返回后,原函数需要继续执行的地址),方便CPU去执行.

原文地址:https://www.cnblogs.com/davytitan/p/12095306.html