条件转移指令

Tutorial: 汇编基础 Category: C语言 Published: 2026-04-07 13:58:26 Views: 21 Likes: 0 Comments: 0
1. jcxz = jmp cx zero
  • 条件: if cx == 0
  • 范围:短转移 -128 - 127
; 题目:补全程序, 利用jcxz指令, 讲2000H中第一个值为0的字节, 将其偏移地址放到dx中
assume cs:code

data segment
         db 1,2,3,4,5,6,7,8,9,0
data ends

code segment
    start:    call cpy_data
              mov  ax,2000H
              mov  ds,ax
              mov  bx,0

    s:        mov  cx,0
              mov  cl,ds:[bx]
              jcxz ok
              inc  bx
              jmp  s

    ok:       mov  dx,bx
              mov  ax, 4C00H
              int  21H

    ; cpy_data,cpy_data1 只是为了把 data 中的数据复制到2000:0(es)中
    cpy_data: mov  bx, data
              mov  ds,bx
              mov  bx,0
              mov  bx,2000H
              mov  es,bx
              mov  di,0
              mov  cx,10

    ; cpy_data,cpy_data1 只是为了把 data 中的数据复制到2000:0(es)中
    cpy_data1:mov  al, ds:[si]
              mov  es:[di],al
              inc  si
              inc  di
              loop cpy_data1
              ret

code ends
end start
-t

AX=2000  BX=0009  CX=0009  DX=0000  SP=0000  BP=0000  SI=000A  DI=000A
DS=2000  ES=2000  SS=0E23  CS=0E25  IP=0013   NV UP EI PL NZ NA PE NC
0E25:0013 EBF6          JMP     000B
-t

AX=2000  BX=0009  CX=0009  DX=0000  SP=0000  BP=0000  SI=000A  DI=000A
DS=2000  ES=2000  SS=0E23  CS=0E25  IP=000B   NV UP EI PL NZ NA PE NC
0E25:000B B90000        MOV     CX,0000
-t

AX=2000  BX=0009  CX=0000  DX=0000  SP=0000  BP=0000  SI=000A  DI=000A
DS=2000  ES=2000  SS=0E23  CS=0E25  IP=000E   NV UP EI PL NZ NA PE NC
0E25:000E 8A0F          MOV     CL,[BX]                            DS:0009=00
-d ds:0 F
2000:0000  01 02 03 04 05 06 07 08-09 00 00 00 00 00 00 00   ................
-t

AX=2000  BX=0009  CX=0000  DX=0000  SP=0000  BP=0000  SI=000A  DI=000A
DS=2000  ES=2000  SS=0E23  CS=0E25  IP=0010   NV UP EI PL NZ NA PE NC
0E25:0010 E303          JCXZ    0015
-t

AX=2000  BX=0009  CX=0000  DX=0000  SP=0000  BP=0000  SI=000A  DI=000A
DS=2000  ES=2000  SS=0E23  CS=0E25  IP=0015   NV UP EI PL NZ NA PE NC
0E25:0015 8BD3          MOV     DX,BX
-t

AX=2000  BX=0009  CX=0000  DX=0009  SP=0000  BP=0000  SI=000A  DI=000A
DS=2000  ES=2000  SS=0E23  CS=0E25  IP=0017   NV UP EI PL NZ NA PE NC
0E25:0017 B8004C        MOV     AX,4C00
2. loop
  • 条件:cx = cx -1
  • cx != 0: 跳转到标号
  • cx == 0: 终止循环
assume cs:code
; 题目:利用loop指令, 将2000H中第一个值为0的字节, 将其偏移地址放到dx中

data segment
         db 1,2,3,4,5,6,7,8,9,0
data ends

code segment

    start:    call cpy_data
              mov  ax,2000H
              mov  ds,ax
              mov  bx,0

    s:        mov  cl,ds:[bx]
              mov  ch,0
              inc  cx
              inc  bx
              loop s              ; cx --

    ok:       dec  bx
              mov  dx,bx
              mov  ax, 4C00H
              int  21H

    ; cpy_data,cpy_data1 只是为了把 data 中的数据复制到2000:0(es)中
    cpy_data: mov  bx, data
              mov  ds,bx
              mov  bx,0
              mov  bx,2000H
              mov  es,bx
              mov  di,0
              mov  cx,10

    ; cpy_data,cpy_data1 只是为了把 data 中的数据复制到2000:0(es)中
    cpy_data1:mov  al, ds:[si]
              mov  es:[di],al
              inc  si
              inc  di
              loop cpy_data1
              ret

code ends
end start
-d ds:0 f
2000:0000  01 02 03 04 05 06 07 08-09 00 00 00 00 00 00 00   ................
-t

AX=2000  BX=0009  CX=0009  DX=0000  SP=0000  BP=0000  SI=000A  DI=000A
DS=2000  ES=2000  SS=0E23  CS=0E25  IP=000B   NV UP EI PL NZ NA PE NC
0E25:000B 8A0F          MOV     CL,[BX]                            DS:0009=00
-t

AX=2000  BX=0009  CX=0000  DX=0000  SP=0000  BP=0000  SI=000A  DI=000A
DS=2000  ES=2000  SS=0E23  CS=0E25  IP=000D   NV UP EI PL NZ NA PE NC
0E25:000D B500          MOV     CH,00
-t

AX=2000  BX=0009  CX=0000  DX=0000  SP=0000  BP=0000  SI=000A  DI=000A
DS=2000  ES=2000  SS=0E23  CS=0E25  IP=000F   NV UP EI PL NZ NA PE NC
0E25:000F 41            INC     CX
-t

AX=2000  BX=0009  CX=0001  DX=0000  SP=0000  BP=0000  SI=000A  DI=000A
DS=2000  ES=2000  SS=0E23  CS=0E25  IP=0010   NV UP EI PL NZ NA PO NC
0E25:0010 43            INC     BX
-t

AX=2000  BX=000A  CX=0001  DX=0000  SP=0000  BP=0000  SI=000A  DI=000A
DS=2000  ES=2000  SS=0E23  CS=0E25  IP=0011   NV UP EI PL NZ NA PE NC
0E25:0011 E2F8          LOOP    000B
-t

AX=2000  BX=000A  CX=0000  DX=0000  SP=0000  BP=0000  SI=000A  DI=000A
DS=2000  ES=2000  SS=0E23  CS=0E25  IP=0013   NV UP EI PL NZ NA PE NC
0E25:0013 4B            DEC     BX
-t

AX=2000  BX=0009  CX=0000  DX=0000  SP=0000  BP=0000  SI=000A  DI=000A
DS=2000  ES=2000  SS=0E23  CS=0E25  IP=0014   NV UP EI PL NZ NA PE NC
0E25:0014 8BD3          MOV     DX,BX
-t

AX=2000  BX=0009  CX=0000  DX=0009  SP=0000  BP=0000  SI=000A  DI=000A
DS=2000  ES=2000  SS=0E23  CS=0E25  IP=0016   NV UP EI PL NZ NA PE NC
0E25:0016 B8004C        MOV     AX,4C00
3. 实验 8
assume cs:code
code segment
            mov ax,4C00H
            int 21H

      start:                      ; 0005
            mov ax,0
      s:
            nop
            nop
            mov di,offset s       ; 0008
            mov si,offset s2      ; 0020
            mov ax,cs:[si]        ; F6EB
            mov cs:[di],ax        ; 0E24:0008 900E24:0009 90
                                  ; 替换为 0E24:0008 EBF6  => JMP     0000

      s0:
            jmp short s

      s1:
            mov ax,0
            int 21H
            mov ax,0

      s2:
            jmp short s1           ; EBF6, 把它移动到 0E24:0008, 只是借用了地址段里面的内容
            nop

code ends
end start
-u 0e24:0
0E24:0000 B8004C        MOV     AX,4C00
0E24:0003 CD21          INT     21
0E24:0005 B80000        MOV     AX,0000
0E24:0008 90            NOP
0E24:0009 90            NOP
0E24:000A BF0800        MOV     DI,0008
0E24:000D BE2000        MOV     SI,0020
0E24:0010 2E            CS:
0E24:0011 8B04          MOV     AX,[SI]
0E24:0013 2E            CS:
0E24:0014 8905          MOV     [DI],AX
0E24:0016 EBF0          JMP     0008      ; s0
0E24:0018 B80000        MOV     AX,0000   ; s1
0E24:001B CD21          INT     21
0E24:001D B80000        MOV     AX,0000
0E24:0020 EBF6          JMP     0018      ; s2
0E24:0022 90            NOP

-d cs:0
0E24:0000  B8 00 4C CD 21 B8 00 00-90 90 BF 08 00 BE 20 00   ..L.!......... .
0E24:0010  2E 8B 04 2E 89 05 EB F0-B8 00 00 CD 21 B8 00 00   ............!...
0E24:0020  EB F6 90 13 8F 06 74 13-50 EA 6D 06 58 00 06 2E   ......t.P.m.X...
0E24:0030  8E 06 00 00 26 8F 06 7E-13 26 8F 06 3A 00 26 8F   ....&..~.&..:.&.
0E24:0040  06 3C 00 26 8F 06 78 13-60 1E 26 8B 36 3A 00 26   .<.&..x.`.&.6:.&
0E24:0050  8E 1E 3C 00 8A 14 32 F6-8B 44 01 26 A3 82 13 03   ..<...2..D.&....
0E24:0060  D2 26 8B 3E 4E 13 8C D8-83 FF 00 74 1D 8E DF 8B   .&.>N......t....
0E24:0070  36 04 00 8B 3E 00 00 03-F6 74 ED 8B 5C 0E E8 12   6...>....t..\...

最终:
-u cs:0
0E24:0000 B8004C        MOV     AX,4C00
0E24:0003 CD21          INT     21
0E24:0005 B80000        MOV     AX,0000
0E24:0008 EBF6          JMP     0000
0E24:000A BF0800        MOV     DI,0008
0E24:000D BE2000        MOV     SI,0020
0E24:0010 2E            CS:
0E24:0011 8B04          MOV     AX,[SI]
0E24:0013 2E            CS:
0E24:0014 8905          MOV     [DI],AX
0E24:0016 EBF0          JMP     0008
0E24:0018 B80000        MOV     AX,0000
0E24:001B CD21          INT     21
0E24:001D B80000        MOV     AX,0000
-r
AX=F6EB  BX=0000  CX=0023  DX=0000  SP=0000  BP=0000  SI=0020  DI=0008
DS=0E14  ES=0E14  SS=0E23  CS=0E24  IP=0016   NV UP EI PL NZ NA PO NC
0E24:0016 EBF0          JMP     0008
-t

AX=F6EB  BX=0000  CX=0023  DX=0000  SP=0000  BP=0000  SI=0020  DI=0008
DS=0E14  ES=0E14  SS=0E23  CS=0E24  IP=0008   NV UP EI PL NZ NA PO NC
0E24:0008 EBF6          JMP     0000
-t

AX=F6EB  BX=0000  CX=0023  DX=0000  SP=0000  BP=0000  SI=0020  DI=0008
DS=0E14  ES=0E14  SS=0E23  CS=0E24  IP=0000   NV UP EI PL NZ NA PO NC
0E24:0000 B8004C        MOV     AX,4C00
4. 概念
  1. 同时修改 CS 和 IP 时, 称为段间转移, 比如:jmp 100:2a7。

    • jmp far ptr 标号
  2. 只修改 IP 时, 称为段内转移, 比如:jmp ax。

    • 由于转移指令对 IP 的修改范围不同, 段内转移又分为"短转移"和"近转移"。
  3. 段内短转移 IP 的修改范围为-128~127。如 Jmp short 标号(转到标号处执行指令)

    • 它对 IP 的修改范围为-128~127, 也就是说, 它向前转移时可以
    • 最多越过 128 个字节, 向后转移可以最多越过 127 个字节。
  4. 段内近转移 IP 的修改范围为-32768~32767。

    • jmp near ptr 标号"的功能为:IP=IP + 16 位位移
  5. 标号处的地址 - jmp 指令后第一个字节的地址 = 位移 标号地址 = jmp 指令后的第一个字节地址 + 位移

    • jmp 指令的机器指令并不包含目的地址, 包含的是相对于当前 IP 的转移位移, CPU 并不需要目的地址就可以实现对 IP 的修改。
    • 0003 机器码 EB03, 这个机器码中竟不包含转移的目的地址, 这意味着, CPU 在执行 EB03 的时候, 并不知道转移的目的地址。那么, CPU 根据什么进行转移呢?它知道转移到哪里呢?
    • 05 + EB(03) = 08
    • 08 - 05 = 03
    • jmp short 指令的操作码是 EB, 位移是 03
assume cs:code
code segment

      start:mov ax,0
            jmp short s
            add ax,1

      s:    inc ax
            mov ax,4c00h
            int 21h

code ends
end start
-u
0E24:0000 B80000        MOV     AX,0000
0E24:0003 EB03          JMP     0008
0E24:0005 83C001        ADD     AX,+01
0E24:0008 40            INC     AX
0E24:0009 B8004C        MOV     AX,4C00
0E24:000C CD21          INT     21
  1. 同样的, 计算实验 8
    • 标号处的地址 = jmp 指令后第一个字节的地址 + 位移
    • 标号处的地址 = 0018 + (EB)F0 = 18 + F0 = 0008
    • 然后 EBF6 = EB => jmp, F6 位移 ; 现在是知道位移了, 不知道标号地址
    • 标号处的地址 = 000A + F6(1111 0110) = 0A + -(00001001 + 1) = 0A + -(1010(A)) = A - A = 0
    • 即:jmp 0000
-u
0E24:0000 B8004C        MOV     AX,4C00
0E24:0003 CD21          INT     21
0E24:0005 B80000        MOV     AX,0000
0E24:0008 EBF6          JMP     0000
0E24:000A BF0800        MOV     DI,0008
0E24:000D BE2000        MOV     SI,0020
0E24:0010 2E            CS:
0E24:0011 8B04          MOV     AX,[SI]
0E24:0013 2E            CS:
0E24:0014 8905          MOV     [DI],AX
0E24:0016 EBF0          JMP     0008
0E24:0018 B80000        MOV     AX,0000
0E24:001B CD21          INT     21
0E24:001D B80000        MOV     AX,0000
Prev: 转移指令 Next: 实验九