汇编语言(第三版,王爽)读书笔记
CALL和RET指令
ret和retf
- ret指令用栈中的数据,修改ip的内容,从而实现近转移
cpu执行ret时:
(1)(ip)=((ss)* 16+(sp))
(2)(sp)=(sp)+2 - retf指令用栈中的数据,修改cs和ip的内容,从而实现远转移
cpu执行retf时:
(1)(ip)=((ss))* 16+(sp))
(2)(sp)=(sp)+2
(3)(cs)=((ss)* 16+(sp))
(4)(sp)=(sp)+2
call指令
cpu执行call指令时,进行两步操作:
(1)将当前的ip或cs和ip压入栈中
(2)转移
call指令不能使用短转移,其他用法和jmp指令原理相同。
依据位移进行转移的call指令
call 标号
将当前的ip压栈后,转到标号处执行指令
cpu进行如下操作:
- (sp)=(sp)-2
- ((ss)* 16+(sp))=(ip)
- (ip)=(ip)+16位位移
16位位移由编译程序在编译时算出
相当于进行:push ip
、jmp near ptr 标号
(近转移)
转移的目的地址在指令中的call指令
call far ptr 标号
实现的是段间转移
相当于进行push cs
、push ip
、jmp far ptr 标号
转移地址在寄存器中的call指令
call 16位reg
相当于进行push ip
、jmp 16位reg
转移地址在内存中的call指令
call word ptr 内存单元地址
相当于进行push ip
、jmp word ptr 内存单元地址
ret和call的配合使用
利用ret和call实现子程序机制,框架如下:
assume cs:code
code segment
main: ...
...
call sub1 ;调用子程序sub1
...
...
mov ax,4c00h
int 21h
sub1: ...
...
call sub2
...
ret ;子程序返回
sub2: ...
...
ret ;子程序返回
code ends
end main
利用call和ret指令,我们可以用简捷的方法,实现多个相互联系、功能独立的子程序来解决一个复杂问题。
mul指令
mul是乘法指令
- 两个相乘的数,要么都是8位,要么都是16位;如果是8位,一个默认放在AL中,另一个放在8位reg或者内存单元中;如果是16位,一个默认放在AX中,另一个放在16位reg或内存字单元中。
- 结果,如果是8位乘法,结果默认在AX中,如果是16位乘法,结果高位默认在dx中存放,低位在ax中放。
参数和结果传递的问题
应该如何储存子程序需要的参数和产生的返回值
例如计算N的三次方:
cube: mov ax,bx
mul bx
mul bx
ret
可以将参数N放到bx中,结果放到dx,ax中
批量传递数据
但是寄存器的数量有限,不能将所有的参数放入其中,批量数据可以放到内存中,然后将它们所在内存空间的首地址放在寄存器中,传递给子程序,批量返回结果也可以使用此方法。
除了用寄存器传递参数外,还可以用栈来转递
寄存器冲突的问题
为了防止主程序中使用的寄存器,子程序也要使用,更改子程序标准框架如下:
子程序开始:子程序使用的寄存器入栈
子程序内容
子程序中使用的寄存器出栈
返回(ret、retf)