您的位置 首页 动态

8086指令系统—操控搬运指令(二)

3循环指令这一组指令在循环结构的程序中用来控制一段程序(称为循环体)的重复执行,在汇编指令中循环的转向地址用标号来表示,

  3 循环指令

  这一组指令在循环结构的程序中用来操控一段程序(称为循环体)的重复履行,在汇编指令中循环的转向地址用标号来表明,而在机器指令中给出的是位移量,所以履行循环指令时,若满意循环条件,CPU就核算转向地址:(IP)当时+8位位移量→(IP),即完结循环。

  若不满意循环条件,即退出循环,程序持续次序履行。
  循环指令都是短搬运格局的指令,也就是说,位移量是用8位带符号数来表明的,转向地址在相对于当时IP值的-128 ~ +127字节规模之内。

  对条件循环指令LOOPZ(LOOPE)和LOOPNZ(LOOPNE),除测验CX中的循环次数外,还将ZF的值作为循环的必要条件,因而,要留意将条件循环指令紧接在构成ZF的指令之后。

  在多重循环的程序结构中,假如各层循环都运用循环指令来操控,则应留意对CX中循环计数值的保存与康复。
循环指令均不影响条件码。

  LOOP  label    循环(loop)
  履行操作:① (CX)←(CX)-1
       ② 若(CX)≠0,则(IP)←(IP)当时+位移量,不然循环完毕

  LOOPZ/LOOPE label 为零/持平时循环(loop while zero,or equal)
  履行操作:① (CX)←(CX)-1
       ② 若ZF=1且(CX)≠0,则(IP)←(IP)当时+位移量,不然循环完毕

  LOOPNZ/LOOPNE label 不为零/不等时循环(loop while nonzero,or not equal)
  履行操作:① (CX)←(CX)-1
       ② 若ZF=0且(CX)≠0,则(IP)←(IP)当时+位移量,不然循环完毕

例编写程序,完结两个数据块BLOCK1和BLOCK2相加,成果存入BLOCK2。
       DATA   SEGMENT
       BLOCK1   DW   100 DUP(?)
       BLOCK2   DW   100 DUP(?)
       DATA  ENDS
       ; – – – – – – – – – – – – – – – – – –
       CODE   SEGMENT
       ASSUME CS:CODE,DS:DATA,ES:DATA
    START:MOV   AX,DATA
       MOV   DS,AX        ; initialize the data segment
       MOV   ES,AX        ; initialize the extra segment
       CLD             ; DF=0 for autoincrement
       MOV   CX,100        ; load the counter
       MOV   SI,OFFSET BLOCK1  ; address of block1
       MOV   DI,OFFSET BLOCK2  ; address of block2
    NEXT: LODSW            ; load the data of block1 into AX
       ADD   AX,ES:[DI]     ; add the data of block2 to AX
       STOSW            ; store the sum to block2
       LOOP   NEXT        ; repeat 100 times
       MOV   AX,4C00H      ; return to DOS
       INT   21H
    CODE  ENDS
       END   START

 4 子程序调用与回来指令

  子程序是一种非常重要的核算机编程结构,它存储在存储器中,可供一个或多个调用程序(主程序)重复调用。主程序调用子程序时运用CALL指令,由子程序回来主程序时运用RET指令。因为调用程序和子程序能够在同一个代码段中,也能够在不同的代码段中,因而,CALL指令和RET指令也有近调用、近回来及远调用、远回来两类格局。

 ⑴ CALL NEAR PTR SUBPROUT 近调用(near call)
  近调用是CALL指令的缺省格局,能够写为”CALL subrotine”。它调用同一个代码段内的子程序(子进程),因而,在调用进程中不必改动CS的值,只需将子程序的地址存入IP寄存器。CALL指令中的调用地址能够用直接和直接两种寻址方法表明。

 ⑵ CALL FAR PTR SUBPROUT 远调用(far call)
  远调用适用于调用程序(也称为主程序)和子程序不在同一段中的状况,所以也叫做段间调用。和近调用指令相同,远调用指令中的寻址方法也可用直接方法和直接方法。

 ⑶ RET 回来指令(return)
  RET指令履行的操作是把保存在仓库中的回来地址出栈,以完结从子程序回来到调用程序的功用。

  ● CALL SUBROUT 段内直接调用
  履行操作:① (SP) ← (SP)-2,((SP)) ← (IP)当时
       ② (IP) ← (IP)当时+16位位移量(在指令的第2、3个字节中)
  
  ● CALL DESTIN 段内直接调用
  履行操作:① (SP) ← (SP)-2,((SP)) ← (IP)当时
       ② (IP) ← (EA) ; (EA)为指令寻址方法所确认的有用地址

  ● CALL FAR PTR SUBROUT 段间直接调用
  履行操作:① (SP) ← (SP)-2,((SP)) ← (CS)当时
         (SP) ← (SP)-2,((SP)) ← (IP)当时
       ② (IP) ← 偏移地址(在指令的第2、3个字节中)
         (CS) ← 段地址(在指令的第4、5个字节中)

  ● CALL WORD PTR DESTIN 段间直接调用
  履行操作:① (SP) ← (SP)-2,((SP)) ← (CS)当时
         (SP) ← (SP)-2,((SP)) ← (IP)当时
       ② (IP) ← (EA) ; (EA)为指令寻址方法所确认的有用地址
         (CS) ← (EA+2)

  从CALL指令履行的操作能够看出,第一步是把子程序回来调用程序的地址保存在仓库中。对段内调用,只需将IP的当时值,即CALL指令的下一条指令的地址存入SP所指示的仓库字单元中。对段间调用,保存回来地址则意味着要将CS和IP的当时值别离存入仓库的两个字单元中。

  CALL指令的第二步操作是转子程序,即把子程序的进口地址交给IP(段内调用)或CS:IP(段间调用)。对段内直接方法,调转的位移量,即子程序的进口地址和回来地址之间的差值就在机器指令的2、3字节中。对段间直接方法,子程序的偏移地址和段地址就在操作码之后的两个字中。对直接方法,子程序的进口地址就从寻址方法所确认的有用地址中取得。

  ● RET 段内回来(近回来)
  履行操作:(IP) ← ((SP)),(SP) ← (SP)+2

  ● RET 段间回来(远回来)
  履行操作:(IP) ← ((SP)),(SP) ← (SP)+2
       (CS) ←((SP)),(SP) ← (SP)+2

  ● RET N 带当即数回来
  履行操作:① 回来地址出栈(操作同段内或段间回来)
       ② 修正仓库指针:(SP) ← (SP)+N

  子程序的最终一条指令有必要是RET指令,以回来到主程序。假如是段内回来,只需把保存在仓库中的偏移地址出栈存入IP即可,假如是段间回来,则要把偏移地址和段地址都从仓库中取出送到IP和CS寄存器中。

  带当即数回来指令,除完结偏移地址出栈或偏移地址和段地址出栈的操作外,还要再使SP的内容加上一个当即数N,使仓库指针SP移动到新的方位。指令中的N能够是一个常数,也能够是一个表达式。带当即数回来指令适用于C或PASCAL的调用规矩,这些规矩在调用进程(子程序)前先把参数压入仓库,子程序运用这些参数后,假如在回来时丢掉这些已无用的参数,就在RET指令中包括一个数字,它表明压入到仓库中参数的字节数,这样仓库指针就康复到参数入栈前的值。

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

 例依据下面调用程序和子程序的程序清单,画出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 subroutine
    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
    007B  C2      0004 RET 4   ; return and revert SP
    007E  ADDM     ENDP

图 CALL指令和RET指令对仓库的影响

  如图3.12所示,主程序中的两条PUSH指令将数据30和40压入仓库,CALL指令履行后,回来地址000B又压入仓库,紧接着程序操控搬运到子程序ADDM。子程序中的PUSH指令又使BP的值进栈,此刻SP指向栈顶0FFA。MOV指令将0FFA传送给BP,使BP作为寻址仓库数据的指针。(BP+4)指向的是40,(BP+6)指向的是30,取出数据后用POP指令康复了BP原先的值,此刻,(SP)=0FFC,这是RET 4指令履行前的仓库状况。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/news/dongtai/256959.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部