从0学习汇编语言(10) CALL和RET指令

479 阅读3分钟

《从0学习汇编语言目录》

第十章 CALL和RET指令

10.1 ret和retf

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

ret:

  1. (IP) = ((SS) *16 + (SP))
  2. SP = SP + 2

retf

  1. (IP) = ((SS) *16 + (SP))
  2. SP = SP + 2
  3. (CS) = ((SS) *16 + (SP))
  4. SP = SP + 2

10.2 call指令

call:

  1. 把当前IP或者CS和IP放入栈中
  2. 转移

10.3 依据位移进行转移的call指令

call 标号(将当前IP压入栈后,转到标号处执行指令)

  1. (sp) = (sp) - 2 (SS) *16 + SP = (IP)
  2. 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指令

  1. call word ptr 内存地址 相当于
push IP
jmp word ptr 内存单元地址
  1. call dword ptr 内存地址 相当于
push CS
push IP
jmp dword ptr 内存单元地址

10.7 call和ret的配合使用

call 向栈中存入ip 或者cs :ip ,可以配合 retretf 返回。这样就能像调用函数一样调用汇编了

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寄存器冲突问题

  1. 一般来说 参数和结果保存在寄存器中。
  2. 如果大批量传递数据,可以在寄存器中存批量数据的首地址,利用cx或者计算长度等方式,拿到数据
  3. 如果子程序中也用到外面的用到的寄存器怎么办? 例如子程序改变了dx寄存器,而外面dx寄存器保存了其他值。
    1. 一般在子程序中,先用栈来保存当前寄存器的值。

    2. 当程序结束后,在恢复之前寄存器的值。

    3. 这样就保证了,子程序和父程序寄存器冲突的问题了。

《第十一章链接》