第九章 转移指令的原理
可以修改,或同时修改CS和IP的指令统称为转移指令。
只修改IP jmp ax
同时修改CS和IP jmp 1000:0
无条件转移指令jmp
条件转移指令
循环指令
过程
中断
9.1 操作符 offset
由编译器处理的符号 取得标号的偏移地址
start : mov ax, offset start
s: mov ax, offset s
将S处的代码复制到S0处
assume cs:code
code segment
s: mov ax, bx
mov si, offset s
mov di, offset s0
mov ax, cs:[si]
mov cs:[di], ax
s0: nop
nop
code ends
end
运行结果
9.2 jmp指令
jmp给出两种信息
1)转移的目标地址
2)转移的距离(段间转移,段内转移,段内近转移)
9.3 依据位移进行转移段jmp指令
jmp short 标号 段内短转移对IP对修改范围在 -128~127
例子
assume cs:code
code segment
start: mov ax, 0
jmp short s
add ax, 1
s: inc ax
code ends
end start
编译后在debug中对机器码
jmp short s0 被编译成 EB03 并不包含目标地址
CPU在执行jmp指令的时候并不需要转移的目的地址
EB03 表示在当前IP基础上向后位移3个字节的地址 也就是 jmp short s 编译以后包含的数据是位移量
jmp short 标号 (IP) = (IP) + 8位位移量
1)8位位移=标号处的地址-jmp指令后的第一个字节的地址
2)short指明此处的位移为8位位移
3)8位位移的范围是-128~127,用补码表示
4)8位位移由编译程序在编译时算出
还有一种
jmp near ptr 标号 (IP)= (IP)+16位位移
1)16位位移=标号处的地址-jmp指令后的第一个字节的地址
2)near ptr指明此处的位移为16位位移,进行段内近转移
3)16位位移的范围是-32768~32767,用补码表示
4)16位位移由编译程序在编译时算出
9.4 转移的目的地址在指令中的jmp指令
assume cs:code
code segment
start: mov ax, 0
mov bx, 0
jmp far ptr s
db 256 dup (0)
s: add ax, 1
inc ax
code ends
end start
9.5 转移地址在寄存器中的jmp指令
jmp 16位reg
功能 (IP) = (16位reg)
9.6 转移地址中内存中的jmp指令
1)jmp word ptr 内存单元地址(段内转移)
jmp word ptr ds:[0]
jmp word ptr [bx]
2)jmp dword ptr 内存单元地址(段间转移)
二个字单元,高地址字单元存放段地址,低地址字单元存放偏移地址
(CS) = (内存单元地址+2)
(IP) = (内存单元地址)
9.7 jcxz 指令
条件转移指令,所有段条件转移指令都是短转移,对应的机器码中包含转移的位移而不是目的地址。
指令格式
jcxz 标号 (如果(cx)= 0, 转移到标号处执行)
操作 当 (cx)= 0, (IP) = (IP)+ 8位位移
8位位移 = 标号处地址 - JCXZ指令后的第一个字节的地址
8位位移量范围-128~127,用补码表示
8位位移由编译器中编译时算出
当(CX)!=0 时 程序什么也不做
监测点9.2 查找从内存2000H段中第一个值位0段字节,找到后将他的偏移地址存储在dx中
;find the first address from segment 2000H
;with the value of the address equal to zero
assume cs:code
code segment
start: mov ax, 2000h
mov ds, ax
mov bx, 0
s: mov cl, ds:[bx]
mov ch, 0
jcxz ok
inc bx
jmp short s
ok: mov dx, bx
mov ax, 4c00h
int 21h
code ends
end start
9.8 loop 指令
所有循环指令都是短转移,中对应机器码中包含转移的位移,而不是目的地址。
(cx)= (cx) - 1
如果 (cx) != 0 跳转至标号处 (IP)= (IP)+8位位移
8位位移 = 标号处地址 - loop指令后的第一个字节的地址
8位位移量范围-128~127,用补码表示
8位位移由编译器中编译时算出
loop的功能等于 if(cx != 0) jmp short 标号;
检测点9.3
使用loop 在内存2000H处查找第一个值位0的字节
;find the first address from segment 2000H
;with the value of the address equal to zero
assume cs:code
code segment
start: mov ax, 2000h
mov ds, ax
mov bx, 0
s: mov cl, ds:[bx]
mov ch, 0
inc cx
inc bx
loop s
ok: dec bx
mov dx, bx
mov ax, 4c00h
int 21h
code ends
end start
9.9 根据位移进行转移的意义
jmp short 标号
jmp near ptr 标号
jcxz 标号
loop 标号
为了方便程序段在内存中的浮动装配
9.10 编译器对转移位移超界对检测
以下代码编译会报错
assume cs:code
code segment
start: jmp short s
db 255 dup (0)
s: mov ax, 0ffffh
code ends
end start
实验8
分析以下程序是否可以运行
assume cs:codesg
codesg segment
mov ax, 4c00h
int 21h
start: mov ax, 0
s: nop
nop
mov di, offset s
mov si, offset s2
mov ax, cs:[si]
mov cs:[di], ax
s0: jmp short s
s1: mov ax, 0
int 21h
mov ax, 0
s2: jmp short s1
nop
codesg ends
end start
可以看到,程序可以正常返回。利用来位移jmp最终程序跳转到开头的mov ax,4c00h 和 int 21h
实验9 根据实验材料编程在屏幕中央输出彩色字符
assume cs:code, ds:data, ss:stack
;the data segment store the string and the color info
data segment
;00h
db 'welcome to masm!' ;16 character
;10h
db 2h ; bkColor = black, color = green (0 000 0 010B)
db 24h ; bkColor = green, color = red (0 010 0 100B)
db 71h ; bkColor = white, color = blue (0 111 0 001B)
;13h
dw 5a0h ; map to the start 11th line position of the VRAM 5a0h + 40h
;15h
dw 40h ; the offset position to write the first character of the line
data ends
stack segment
db 16 dup (0)
stack ends
code segment
start: mov ax, data ; map ds to data segment
mov ds, ax
mov ax, 0b800h ; map es to vga ram segment
mov es, ax
mov ax, stack ; map ss to stack segment
mov ss, ax
mov sp, 10h
; init reg
mov cx, 3 ; write for three line
mov bx, 0 ; for line number
mov bp, ds:[13h] ; load the address fot vram
add bp, ds:[15h] ; add the offset address
s: push cx
mov cx, 16 ; write for 16 characters
mov si, 0 ; pointer to character array
mov di, 0 ; pointer to the target vram
s0: mov al, ds: 00h[si] ; read char to ax
mov ah, ds: 10h[bx] ; read color info
mov es:[bp][di], ax ; store the char and color info to vram
inc si
add di, 2
loop s0
add bp, 0a0h ; point to the next line
inc bx
pop cx
loop s
mov ax, 4c00h
int 21h
code ends
end start