汇编语言阅读笔记【转移指令】

一、参考

汇编语言-王爽

二、正文

可以修改IP,或者同时修改CS和IP的指令统称为转移指令
转移指令就是可以控制CPU执行内存中某处代码的指令

2.2 CALL和RET指令

call 和 ret指令都是转移指令,都修改IP, 或者同时修改CS和IP,它们经常被共同用于实现子程序的设计。

2.2.1 ret和retf

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

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

实际变更为:
(IP) = ( (ss)*16 + (sp) )
(sp) = (sp) + 2

CPU执行retf指令,相当于进行:
pop IP
pop CS

实际变更为:

(IP) = ( (ss)*16 + (sp) )
(sp) = (sp) + 2
(CS) = ( (ss)*16 + (sp) )
(sp) = (sp) + 2

2.2.2 call

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

call指令不能实现短转移

2.2.3 call和ret配合使用

2.3 模块化程序设计

call和ret指令共同支持了汇编语言编程中的模块化设计,在实际的编程中,程序的模块化必不可少,
因为现实问题比较复杂,对现实问题进行分析,需要将其转化成为相互联系、不同层次的子问题,这是必须解决的方式,利用call和ret指令,可以用简洁的方法,实现多个相互联系、功能独立的子程序,用于解决一个复杂的问题。

2.3.2 寄存器冲突

子程序中使用的寄存器,很可能在主程序中也要使用,造成了寄存器使用上的冲突

如何避免这种冲突呢?可能存在以下两个方案:
(1)在编写子程序的程序时候,注意查看子程序中有没有用到会产生冲突的寄存器,如果有,调用者使用别的寄存器;
(2)在编写子程序时候,不要使用会产生冲突的寄存器

分析两个方案的可行性:
(1)这将给调用子程序的程序的编写造成很大的麻烦,因为必须要小心检查子程序中是否有将产生冲突的寄存器,例如:如果子程序中使用了寄存器bx和cx,则主程序(调用者)不能使用bx, cx寄存器
(2)该方案不能实现,因为编写子程序的时候,无法知道将来的调用情况

上面的设想都不可行,我们希望:
(1)编写调用子程序的程序的时候,不必关心子程序到底使用了哪些寄存器;
(2)编写子程序的时候,不必关心调用者使用了哪些寄存器;
(3)不会发生寄存器冲突

解决问题的简洁方法是:在子程序开始将子程序中所有用到的寄存器的内容都保存起来,在子程序返回前再恢复,可以使用栈来保存寄存器中的内容

image.png