条件转移指令
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 90 和 0E24: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. 概念
-
同时修改 CS 和 IP 时, 称为段间转移, 比如:jmp 100:2a7。
- jmp far ptr 标号
-
只修改 IP 时, 称为段内转移, 比如:jmp ax。
- 由于转移指令对 IP 的修改范围不同, 段内转移又分为"短转移"和"近转移"。
-
段内短转移 IP 的修改范围为-128~127。如 Jmp short 标号(转到标号处执行指令)
- 它对 IP 的修改范围为-128~127, 也就是说, 它向前转移时可以
- 最多越过 128 个字节, 向后转移可以最多越过 127 个字节。
-
段内近转移 IP 的修改范围为-32768~32767。
- jmp near ptr 标号"的功能为:IP=IP + 16 位位移
-
标号处的地址 - 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
- 同样的, 计算实验 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