汇编语言 第十章 CALL和RET指令

cell 和 ret 都是转移指令,都修改 IP。或同时修改 CS 和 IP。

10.1 ret 和 retf

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

CPU 执行 ret 指令时,进行下面两部操作:

1
2
3
4
5
(IP)=((ss)*16+(sp))
(sp)=(sp)+2

#用汇编语言解释
pop IP

CPU 执行 retf 指令时,进行下面 4 步操作:

1
2
3
4
5
6
7
8
(IP)=((ss)*16+sp)
(sp)=(sp)+2
(CS)=((ss)*16+(sp))
(sp)=(sp)+2

#用汇编语言解释
pop IP
pop CS

10.2 call 指令

CPU 执行 call 指令时,进行两部操作:①将当前的 IP 或 CS 和 IP压入栈中;②转移。

call 指令不能实现短转移,除此之外,call 指令实现转移的方法和 jmp 指令相同。

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

指令格式:call 标号

CPU 执行此种格式的 call 指令时,进行如下操作:

1
2
3
4
5
6
7
(sp)=(sp)-2
((ss*16)+(sp))=(IP)
(IP)=(IP)+16位位移

#用汇编语言解释
push IP
jmp near ptr 标号
  1. 16 位位移=标号处的地址 - call 指令后的第一个字节地址;
  2. 16 位位移的范围为 -32768~32767,用补码表示;
  3. 16 位位移由编译程序在编译时算出。

10.4 转移的目的地址在指令中的 call 指令

前面讲的 call 指令,其对应的机器指令中并没有转移的目的地址,而是相当于对当前 IP 转移位移。

“call far ptr 标号” 实现的是段间转移。(CS)=标号所在段的段地址;(IP)标号在段中的偏移地址。

CPU 执行此种格式的 call 指令时,进行如下操作:

1
2
3
4
5
6
7
8
9
(sp)=(sp)-2
((ss*16)+(sp))=(CS)
(sp)=(sp)-2
((ss)*16+(sp))=(IP)

#用汇编语言解释
push CS
push IP
jmp far ptr 标号

10.5 转移地址在寄存器中的 call 指令

指令格式:call 16位 reg。功能:

1
2
3
4
5
6
7
(sp)=(sp)-2
((ss*16)+(sp))=(IP)
(IP)=(16位reg)

#用汇编语言解释
push IP
jmp 16位reg

10.6 转移地址在内存中的 call 指令

转移地址在内存中的 call 指令有两种格式。

  1. call word ptr 内存单元地址

    1
    2
    3
    #用汇编语言解释
    push IP
    jmp word ptr 内存单元地址
  2. call dword ptr 内存单元地址

    1
    2
    3
    4
    #用汇编语言解释
    push CS
    push IP
    jmp dword ptr 内存单元地址

10.7 call 和 ret 的配合使用

略。

10.8 mul 指令

mul 是乘法指令。两个注意点:

  1. 两个相乘的数:两个相乘的数,要么都是 8 位,要么都是 16 位。如果是 8 位,一个默认放在 AL 中,另一个放在 8 位 reg 或内存字节单元中;如果是 16 位,一个默认在 AX 中,另一个放在 16 位 reg 或内存字单元中。
  2. 结果:如果是 8 位乘法,结果默认放在 AX 中;如果是 16 位乘法,结果高位默认在 DX 中存放,低位在 AX 中放。
1
2
3
4
5
6
7
8
9
mul reg
mul 内存单元

mul byte ptr ds:[0]
#含义:(ax)=(al)*((ds)*16+0);

mul word ptr [bx+si+8]
含义:(ax)=(ax)*((ds)*16+(bx)+(si)+8)结果的低16
(dx)=(ax)*((ds)*16+(bx)+(si)+8)结果的高16

10.9 模块化程序设计

10.10 参数和结果的传递

子程序一般都要根据提供的参数处理一定的事务,处理后,将结果(返回值)提供给调用者。用寄存器来存储参数和结果是最常使用的方法。

10.11 批量数据的传递

子程序有多个参数需要传递的时候,我们将批量数据放到内存中,然后将它们所在内存空间的首地址放在寄存器中,传递给需要的子程序。对于具有批量数据的返回结果,也可以用同样的方法。

10.12 寄存器冲突的问题

在子程序开始的开始将子程序中所有用到的寄存器中的内容都保存起来,在子程序返回前再恢复,可以用栈来保存寄存器中的内容。

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×