修改IP或是同时修改CS和IP的指令就是转移指令。
就是可以控制执行内存中某处代码的指令。
8086CPU有两种:
- 修改 IP jmp ax
- 修改CS:IP jmp 1000:0
转移指令对IP的修改范围不同。
- 短转移IP -128~127
- 近转移IP -32768~32767
8080CPU的转移指令分为以下几种:
- 无条件转移 jmp
- 条件转移
- 循环指令 loop
- 过程
- 中断
通过学习无条件转移 jmp来俩理解cpu执行转移的基本原理。
9.1 操作符 offset
offset取得标号处的偏移地址。
assume cs:codesg
codesg segment
start: mov ax,offset.start ;相当于 mov ax,0
s: mov ax,offset s ;相当于 mov ax,3
codesg ends
end start
问题 9.1
mov ax, cs:[si]
mov cs:[di],ax
9.2 jmp 指令
无条件转移指令,改IP或是改CS:IP
需要提供的信息:
- 目的地地址
- 转移的距离
9.3 根据转移进行转移的jmp指令
jmp short 标号;对ip的修改范围为-128~127,例如
assume cs:codesg
codesg segment
start:
mov ax,0
jmp short s
add ax,1
s: inc ax
codesg ends
end start
CPU执行指令过程
- 将CS:IP中的指令放到指令缓冲器中。
- (IP)= (IP)+所读指令的长度——也就是指向下一条指令。
- 执行指令缓冲器中的指令。转到1,重复这个过程。
因为当执行EB03的时候,IP指向的是0003位置,而要到的地方是0006,所以用目的地减去当前
得到 0006-0003 = 0003,所以是03
当执行EBF7的时候,IP 指向的是下一条指令,也就是 IP = 0009,而要到的地方是0000,所以用目的地减去当前IP。得到 IP = 00-09 得到 IP = F7。
9.4 转移的目的地址在指令中的jmp指令
jmp far ptr 标号,相当于改变了CS:IP.
高位的两个字节是段地址,低位的两个字节是偏移地址。
9.5 转移地址在寄存器中的jmp指令
指令格式 jmp 16位 reg,例子:jmp ax ;将ax赋值给IP
9.6 转移地址在内存中的jmp指令
- jmp word ptr 内存单元地址(段内转移)
jmp word ptr ds:[0] ;将ds:[0]给IP
jmp word ptr [bx] 将 (bx)给IP
- jmp dword ptr 内存单元地址(段间转移),高位字是段地址,地位字是偏移地址。
mov ax,0123h
mov ds:[0],ax
mov word ptr ds:[2],0
jmp dword ptr ds,ds:[0] ; cs = 0, ip = 0123h
检测点 9.1
dw 0,0,
mov [bx],bx ;如果是0,要添加 word ptr
mov [bx+2],cs
CS:IP = 0006:00BE
9.7 jcxz 指令
jcxz指令的功能相当于:
if((cx) == 0) short 标号;
检测点 9.2
mov cl,[bx]
mov ch,0
jcxz ok
add bx,1
9.8 loop 指令
loop为循环转移
,所有的循环转移都是短指令。
检测点 9.3
inc cx
9.9 根据唯一进行转移的意义
这种设计是为了方便程序段在内存中的浮动装配。
9.10 编译器对转移位移超界的检测
assume cs:code
code segment
start: jmp short s ;因为是短转移,范围在-128到127之间,所以128 dup完全超过了127,属于越界了。
db 128 dup(0)
s: mov ax,0ffffh
code ends
end start
实验8 分析一个奇怪的程序
看到 076A:0020 EBF6 就是 s2: jmp short s1
因为S:中在运行时,将其复制到s:中
所以 变成 S: EBF6 ,F6是 -10,所以向前回10个字节。,我们看到目前的指令位置是0008和0009,所以下一条指令地址为000A,再向前10字节,就到达0000偏移地址。
我们看到 0000 的位置后正是程序结束的两个指令。
所以该程序可以执行。
该程序最值得注意的是它将jmp 命令搬到了其他地方,尽管jmp指令是相对于目标的长度,但是由于是直接copy的代码,所以直接执行了原来的 EBF6 代码。
实验 9 根据材料编程
assume cs:codesg,ds:datasg
datasg segment
db 'welcome to masm!'
datasg ends
codesg segment
start:
mov ax,datasg
mov ds,ax
mov ax,0b800h
mov es,ax
mov bx,0
mov di,0
mov si,0820h+56
mov cx,7
s: mov al,[di]
mov ah,00001010b
mov es:[si],ax
add si,2
inc di
loop s
;空格
mov al,[di]
mov ah,00000111b
mov es:[si],ax
inc di
add si,2
mov cx,2
s0: mov al,[di]
mov ah,00101100b
mov es:[si],ax
add si,2
inc di
loop s0
;空格
mov al,[di]
mov ah,00000111b
mov es:[si],ax
inc di
add si,2
mov cx,5
s1: mov al,[di]
mov ah,01110001b
mov es:[si],ax
add si,2
inc di
loop s1
mov ax,4c00h
int 21h
codesg ends
end start
运行结果: