第十章 CALL和RET指令
10.1 ret和retf
ret指令用栈中的数据,修改IP的内容,实现近转移 retf指令用栈中的数据,修改CS和IP内容,实现远转移
ret:
- (IP) = ((SS) *16 + (SP))
- SP = SP + 2
retf
- (IP) = ((SS) *16 + (SP))
- SP = SP + 2
- (CS) = ((SS) *16 + (SP))
- SP = SP + 2
10.2 call指令
call:
- 把当前
IP
或者CS和IP
放入栈中 - 转移
10.3 依据位移进行转移的call指令
call 标号(将当前IP压入栈后,转到标号处执行指令)
- (sp) = (sp) - 2 (SS) *16 + SP = (IP)
- IP = IP + 16位位移
相当于 push ip jmp near ptr 标号
10.4 转移的目的地址在指令中的call指令
call far ptr 标号
相当于:
push CS
push IP
jmp far ptr 标号
10.5 转移地址在寄存器中的call指令
call 16位reg
相当于:
push IP
jmp 16位reg
10.6 转移地址在内存中的call指令
call word ptr 内存地址
相当于
push IP
jmp word ptr 内存单元地址
- call dword ptr 内存地址 相当于
push CS
push IP
jmp dword ptr 内存单元地址
10.7 call和ret的配合使用
call 向栈中存入ip
或者cs :ip
,可以配合 ret
和retf
返回。这样就能像调用函数一样调用汇编了
10.8 mul指令
前提: 乘数的两个数,位数相等,要不都是8位 要不都是16位。 如果 乘数是8位,结果为16位 如果 乘数是16位,结果为32位
乘数一个如果为16位就在AX中。 如果是8位就默认在AL中 另一个乘数在另一个寄存器,或者内存单元中
结果: 如果结果为16位,就放在AX中,如果结果为32位,AX存低16位。DX存高16位
例如
mul byte ptr ds:[0]
byte 为1个字节,所以取ds:[0]中的1个字节(8位)为乘数, 另一个乘数则为 al 因为乘数为8位,所以结果存在AX = al *(ds:[0])
mul word ptr ds:[0]
word 为1个字,所以取ds:[0]中的1个字(16位)为乘数, 另一个乘数则为 ax 因为乘数为32位,所以结果存在AX和DX中
10.10 参数和结果传递问题 & 10.11批量数据传递问题 &12寄存器冲突问题
- 一般来说 参数和结果保存在寄存器中。
- 如果大批量传递数据,可以在寄存器中存批量数据的首地址,利用cx或者计算长度等方式,拿到数据
- 如果子程序中也用到外面的用到的寄存器怎么办? 例如子程序改变了dx寄存器,而外面dx寄存器保存了其他值。
-
一般在子程序中,先用栈来保存当前寄存器的值。
-
当程序结束后,在恢复之前寄存器的值。
-
这样就保证了,子程序和父程序寄存器冲突的问题了。
-
《第十一章链接》