admin 管理员组

文章数量: 1184232


2024年3月19日发(作者:尚硅谷java)

  ● CALL WORD PTR DESTIN 段间间接调用

  执行操作:① (SP) ← (SP)-2,((SP)) ← (CS)当前

         (SP) ← (SP)-2,((SP)) ← (IP)当前

  ● CALL FAR PTR <子程序名> 段间直接调用

  执行操作:① (SP) ← (SP)-2,((SP)) ← (CS)当前

         (SP) ← (SP)-2,((SP)) ← (IP)当前

       ② (IP) ← 偏移地址(在指令的第2、3个字节中)

         (CS) ← 段地址(在指令的第4、5个字节中)

       ② (IP) ← (EA) ; (EA)为指令寻址方式所确定的有效地址

         (CS) ← (EA+2)

       ② (IP) ← (EA) ; (EA)为指令寻址方式所确定的有效地址

       ② (IP) ← (IP)当前+16位位移量(在指令的第2、3个字节中)

  

  ● CALL DESTIN 段内间接调用

  执行操作:① (SP) ← (SP)-2,((SP)) ← (IP)当前

1

2

0

1

6

2

8

1

4

2

 ⑵ CALL FAR PTR <子程序名> 远调用(far call)

  远调用适用于调用程序(也称为主程序)和子程序不在同一段中的情况,所以也叫做

段间调用。和近调用指令一样,远调用指令中的寻址方式也可用直接方式和间接方式。

子程序存储在存储器中,可供一个或多个调用程序(主程序)反复调用。主程序调用子程

序时使用CALL指令,由子程序返回主程序时使用RET指令。由于调用程序和子程序可以

在同一个代码段中,也可以在不同的代码段中,因此,CALL指令和RET指令也有近调用、

近返回及远调用、远返回两类格式。

 ⑴ CALL NEAR PTR <子程序名> 近调用(near call)

  近调用是CALL指令的缺省格式,可以写为"CALL <子程序名>rotine"。它调用同一个

代码段内的子程序(子过程),因此,在调用过程中不用改变CS的值,只需将子程序的地

址存入IP寄存器。CALL指令中的调用地址可以用直接和间接两种寻址方式表示。

 ⑶ RET 返回指令(return)

  RET指令执行的操作是把保存在堆栈中的返回地址出栈,以完成从子程序返回到调用

程序的功能。

● CALL <子程序名> 段内直接调用

  执行操作:① (SP) ← (SP)-2,((SP)) ← (IP)当前

  从CALL指令执行的操作可以看出,第一步是把子程序返回调用程序的地址保存在堆

栈中。对段内调用,只需将IP的当前值,即CALL指令的下一条指令的地址存入SP所指

示的堆栈字单元中。对段间调用,保存返回地址则意味着要将CS和IP的当前值分别存入

堆栈的两个字单元中。

  CALL指令的第二步操作是转子程序,即把子程序的入口地址交给IP(段内调用)或

CS:IP(段间调用)。对段内直接方式,调转的位移量,即子程序的入口地址和返回地址之

  子程序的最后一条指令必须是RET指令,以返回到主程序。如果是段内返回,只需把

保存在堆栈中的偏移地址出栈存入IP即可,如果是段间返回,则要把偏移地址和段地址都

从堆栈中取出送到IP和CS寄存器中。

  CALL指令和RET指令都不影响条件码。

  ● RET 段内返回(近返回)

  执行操作:(IP) ← ((SP)),(SP) ← (SP)+2

  ● RET 段间返回(远返回)

  执行操作:(IP) ← ((SP)),(SP) ← (SP)+2

       (CS) ←((SP)),(SP) ← (SP)+2

  ● RET N 带立即数返回

  执行操作:① 返回地址出栈(操作同段内或段间返回)

       ② 修改堆栈指针:(SP) ← (SP)+N

间的差值就在机器指令的2、3字节中。对段间直接方式,子程序的偏移地址和段地址就在

操作码之后的两个字中。对间接方式,子程序的入口地址就从寻址方式所确定的有效地址

中获得。

1

2

0

1

6

2

8

1

4

2

  带立即数返回指令,除完成偏移地址出栈或偏移地址和段地址出栈的操作外,还要再

使SP的内容加上一个立即数N,使堆栈指针SP移动到新的位置。指令中的N可以是一个

常数,也可以是一个表达式。带立即数返回指令适用于C或PASCAL的调用规则,这些规

则在调用过程(子程序)前先把参数压入堆栈,子程序使用这些参数后,如果在返回时丢

弃这些已无用的参数,就在RET指令中包含一个数字,它表示压入到堆栈中参数的字节数,

这样堆栈指针就恢复到参数入栈前的值。

 例3.43 根据下面调用程序和子程序的程序清单,画出RET指令执行前和执行后的堆栈

情况。假设初始的SS:SP=A000:1000。

 

    0000  B8 001E   MOV  AX,30

    0003  BB 0028   MOV  BX,40

    0006  50      PUSH AX     ; push data1 into stack

    0007  53      PUSH BX     ; push data2 into stack

    0008  E8 0066   CALL ADDM    ; call <子程序名>

    000B  B4 02    MOV  AH,2

    …   …      …

    0071  ADDM     PROC NEAR  ; entry point (IP)←0071=000b+0066

    0071  55      PUSH BP     ; save BP

    0072  8B E4    MOV  BP,SP    ; addressing the stack with BP

    0074  8B 46 04  MOV  AX,[BP+4] ; get data2 from stack

    0077  03 46 06   ADD  AX,[BP+6] ; add data1

    007A  CD      POP  BP     ; get back BP


本文标签: 地址 指令 调用 子程序