引言

1.8086CPU的转移指令分为以下几个类

1
2
3
4
5
1.无条件转移指令【jmp】
2.条件转移指令
3.循环指令【loop】
4.过程
5.中断

1.操作符offset

1.offset:伪指令,取得标号的偏移地址

1
2
3
4
assume cs:codesg
codesg segment
start:mov ax,offset start ;相当于mov ax,0 就是取得start这个标号的偏移地址
s:mov ax,offset s ;相当于mov ax,3 也是去取得了s这个标号的偏移地址

小小的练习

填写指令,使改程序在运行中将s处的一条指令复制到s0处

1
2
3
4
5
6
7
8
9
10
11
12
assume cs:codesg
codesg segment
s: mov ax,bx ;mov ax,bx的机器码占2个字节
mov si,offset s
mov di,offset s0
__________
__________

s0: nop
nop
codesg ends
end s

分析一下咯

1
2
3
4
5
6
7
8
9
10
1.s和s0处的指令所在的内存地址是多少?
cs:offset s 和 cs:offset s0
因为这个指令是在cs:ip下的咯
2.将s处的指令复制到s0处,将cs:offset s处的数据复制到cs:offset s0处
因为它们底层的代码【二进制】是一样的
3.段地址已知在cs中,偏移地址offset s 和 pffset s0 送入 si和di中

4.要复制的数据长度有多长?
mov ax,bx
指令的 长度是2个字节

程序来咯

1
2
3
4
5
6
7
8
9
10
11
12
assume cs:codesg
codesg segment
s: mov ax,bx ;mov ax,bx的机器码占2个字节
mov si,offset s
mov di,offset s0
mov ax,cs:[si]
mov cs:[di],ax

s0: nop
nop
codesg ends
end s

2.jmp指令

1.jmp为无条件转移,可以只修改IP,也可以同时修改CS和IP

2.jmp指令要给处俩种信息:

1
2
1.转移的目的地址
2.转移的距离(段间转移,段内段转移,段内近转移)

3.依据位移进行转移的jmp指令

1.jmp short 标号(转到标号处执行指令)

1
这种格式的jmp指令实现的是段内短转移,它对IP的修改范围是-128~127,也就是说,它向前可以越过128个字节,向后可以最多越过127个字节【越后面数越大】

比如:

1
2
3
4
5
6
7
8
assume cs:codesg		;左边的程序执行后,ax种的值为1,因为执行
csdesg segment ;jmp short s 后,越过了add ax,1 ip指向
start: mov ax,0 ;了标号s处的inc ax。也就是说程序只进行了
jmp short s ;一次 ax加1操作
add ax,1
s: inc ax ;在这个jmp中所对应的机器码是没有对应的地址的
codesg ends ;而是有偏移地址,某个数 【执行了add IP,某个数】
end start

2.jmp short s指令的读取和执行过程:

1
2
3
4
5
1.(cs)=0BBDH,(IP)=0006,CS:IP指向EB 03(jmp short s 的机器码)
2.读取指令码 EB 03 进入指令缓冲器;
3.(IP)=(IP)+所读指令的长度==>(IP)+2=0008,cs:ip指向add ax,1
4.CPU指向指令缓冲器中的指令EB 03;
5.指令EB 03 执行后,(IP)=000BH,CS:IP指向 inc ax

3.实际上,指令“jmp short 标号”的功能为(IP)=(IP)+8位位移

1
2
3
4
5
6
1.8位位移=“标号”处的地址-jmp指令后的第一个字节的地址;相互减
2.short 指明此处的位移为8位位移
3.8位位移的范围为-128~127,用补码表示
4.8位位移由编译程序在编译时算出

!!它不给地址,只给偏移地址!!

4.还有一种和“jmp short 标号”功能相近的指令格式

==>jmp near ptr 标号

功能就是

IP=IP+16位位移

1
2
3
4
1.16位位移=“标号”处的地址 - jmp指令后的第一个字节的地址
2.near ptr 指明此处的16位位移,进行的是段内进转移
3.16位位移的范围:-32768~32767,用补码表示
4.16位位移由编译程序在编译时算出

4.转移的目的地址在指令中的jmp指令

1.前面讲的jmp指令,其对应的机器码中并没有转移目的的地址,而是相对于当前IP的转移位移

2.现在要有一个新的

jmp far ptr 标号:实现的是段间转移,又称为远转移

1
2
3
1.(CS)=标号所在段的段地址
2.(IP)=标号所在段中的偏移地址
3.far ptr 指明了指令用标号的段地址和偏移地址修改CS和IP
1
2
3
4
5
6
7
8
9
10
assume cs:codesg
codesg segment
start: mov ax,0
mov bx,0
jmp far ptr s ;jmp所对应的机器码其中是包含转移的目标地址的
db 256 dup(0)
s: add ax,1
inc ax
codesg ends
end start

5.转移地址在寄存器中的jmp指令

1.指令格式:jmp 16位的寄存器

功能: IP = (16位寄存器)

1
jmp ax

6.转移地址在内存中的jmp指令有2种格式

1.jmp word ptr 内存单元地址【段内转移】

功能:从内存单元地址开始存放着一个字,是转移的目的的偏移地址

内存单元地址可用寻址方式的任一格式给出

1
2
3
4
mov ax,0123H			mov ax,0123H
mov ds:[0],ax mov [bx],ax
jmp word ptr ds:[0] jmp word ptr [bx]
执行后(IP)=0123H 执行后(IP)=0123H

2.jmp dword ptr 内存单元地址【段间转移】

功能:从内存单元地址处开始存放着2个字,高地址处的字是转移的目的段地址,低地址处是转移的目的的偏移地址

​ (CS)=(内存单元地址+2)

​ (IP)=(内存单元地址)

内存 单元可以由寻址的方式的任意格式给出

1
2
3
4
5
6
7
8
mov ax,0123H
mov ds:[0],ax
mov word ptr ds:[2],0
jmp dword ptr ds:[0]

执行后【高地址种是cs 低地址种是ip】
(CS)=0
(IP)=0123

7.jcxz指令

1.jcxz指令为有条件转移指令,所有的有条件跳转指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围都是-128~127

2.指令格式:jcxz 标号

:如果(cx)=0 则跳转到标号处执行

3.jcxz 标号 指令操作

1
2
3
4
5
6
1.当(cx)=0时,(ip)=(ip)+8位位移
1.8位位移=“标号”处的地址 - jcxz指令后的第一个字节的地址
2.8位位移的范围是-128~127 用补码表示
3.8位位移由编译程序在编译时算出

2.当(cs)!=就什么也不做

相当于

1
2
3
if((cx)==0){
jmp short 标号;
}

8.loop指令

1.loop指令为循环指令,所有的循环指令都是短位移,在对应的机器码中包含转移的位移,而不是目的地址

1
2
3
loop 是用于知道循环次数的循环
(cx)=(cx)-1
jcxz 用于不知道循环次数的循环

9.根据位进行转移的意义

1.前面讲到:

1
2
3
4
jmp short 标号
jmp near ptr 标号
jcxz 标号
loop 标号

这几种汇编指令,它们对IP的修改是根据转移目的地址和转移起始地址之间的位移来进行的。

在它们对应的机器码中不包含位移的目的地址,而包含的是到目的地址的位移距离

2.这样设计是为了,方便了程序段在内存中的浮动装配

1
2
3
4
    mov cx,6		B9 06 00
mov ax,10 B8 10 00
s: add ax,ax 01 C0
loop s E2 FC

3.这段程序在内存中的不同位置都可以正确执行,因为loop s 在执行时只涉及到s 的位移(-4 , 前移4个字节,补码表示为 FCH)而不是s的地址

4.如果loop s的机器码中包含的是s的地址,则就对程序段在内存中的偏移地址就有了严格的限制,就不能封装起来放在其他地方使用

5.因为机器码中包含的是s的地址,如果s处的指令不在目的地址处,程序的执行就会出错

我们之前在第二章中讲到的

jmp cs:ip

这种是在debug中的指令,汇编编译器并不认识

实验8

1
exp8.exe

实验九