title: 汇编笔记_第九章
date: 2018-12-27 21:30:12
- 笔记
categories: - 汇编语言
转移指令的原理
8086CPU的转移指令分为以下几类:
- 无条件转移指令(如:
jmp
) - 条件转移指令
- 循环指令(如:
loop
) - 过程
- 中断
操作符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
例题:
assume cs:codesg
codesg segment
start:
mov ax,bx ;mov ax,bx的机器码占两个字节
mov si,offset start
mov di,offset s0
mov ax,cs:[si]
mov cs:[di],ax
s0:
nop ;nop的机器码占一个字节
nop
codesg ends
end start
jmp指令
- jmp为无条件转移,可以只修改IP,也可以同时修改CS和IP;
- jmp指令要给出两种信息:转移的目的地址、转移的距离(段间转移、段内短转移、段内近转移);
依据位移进行转移的jmp指令
jmp short 标号(转到标号处执行指令)
- 段内短转移
- IP的修改范围为 -128~127;
jmp short 标号
的功能为:
- (IP)=(IP)+8位位移;
- 8位位移=“标号”处的地址-jmp指令后的第一个字节的地址;
- short指明此处的位移位8位位移;
- 8位位移的范围位-128~127,用补码表示;
- 8位位移由编译程序在编译时算出;
CPU在执行jmp short 标号指令时只需知道转移的位移就行;
jmp near ptr 标号
实现 段内近转移,(IP)=(IP)+16位位移;
- 16位位移=“标号”处的地址-jmp指令后的第一个字节的地址;
- near ptr指明此处的位移位16位位移;
- 16位位移的范围位-32769~32767,用补码表示;
- 16位位移由编译程序在编译时算出
转移的目的地址 在指令中 的jmp指令
上面两个jmp指令相当于当前IP的转移位移;
jmp far ptr 标号
实现的是 段间转移,又称远转移;
- (CS)=标号所在段的段地址;
- (IP)=标号所在段中的偏移地址;
- far ptr指明了指令用标号的段地址和偏移地址修改CS和IP;
转移地址在 寄存器 中的jmp指令
指令格式:
jmp 16位寄存器
功能:IP=(16位寄存器);
转移指令在 内存 中的jmp指令
jmp word ptr 内存的单元地址(段内转移)
功能:从内存的单元地址处开始存放着一个字,事转移的目的偏移地址;
mov ax,0123h
mov ds:[0],ax
jmp word ptr ds;[0]
执行后(IP)=0123h
mov ax,0123h
mov [bx],ax
jmp word ptr [bx]
jmp dword ptr 内存单元地址(段间转移)
mov ax,0123h
mov ds:[0],ax
mov word ptr ds:[2],0
jmp dword ptr ds:[0]
执行后(CS)=0,(IP)=0123h,CS:IP指向0000:0123
mov ax,0123h
mov [bx],ax
mov word ptr [bx+2],0
jmp dword ptr[bx]
jcxz指令
- jcxz指令位有条件转移指令;
- 所有的有条件转移指令都是 短转移;
- 对应的机器码中包含转移的 位移,而不是目的地址,对IP的修改范围都为-128~127;
- 指令格式:
jcxz 标号
,(如果(cx)=0,则转移到标号处执行);
例题:利用 jcxz 指令,实现在内存2000h段中查找第一个值为0的字节,找到后将偏移地址存储到dx中:
assume cs:code
code segment
start:
mov ax,2000h
mov ds,ax
mov bx,0
s:
mov ch,0
mov cl,ds:[bx]
jcxz ok
inc bx
jmp short s
ok:
mov dx,bx
mov ax,4c00h
int 21h
code ends
end start
loop指令
- loop为循环指令;
- 所有的循环指令都是短转移;
loop 标号:
- (cx)=(cx)-1;
- 如果 ((cx) eq 0),(IP)=(IP)+8位位移;
- 8位位移=“标号”处的地址-loop指令后的第一个字节的地址;
例题:
;找到2000h段中第一个值为0的字节
assume cs:code
code segment
start:
mov ax,2000H
mob ds,ax
mov bx,0
s:
mov al,[bx]
mov ch,0
inc cx ;若该字节为零,那么现在递增为1,之后的loop会使cx减一为零自动退出循环,
inc bx
loop s
ok:
dec bx ;dec指令的功能和inc相反
mov dx,bx
mov ax,4c00h
int 21h
code ends
end start
根据位移进行转移的意义
jmp short 标号
jmp near ptr 标号
jcxz 标号
loop 标号
对IP的修改是根据转移目的地址和转移起始地址之间的 位移 来进行的,这样设计方便程序段在内存中的浮动装配;
编译器对转移位移超界的检测
原程序中出现转移范围超界的问题时,编译报错;
例如:
assume cs:code
code segment
start:
jmp short s
db 128 dup(0)
s:
mov ax,0ffffh
code ends
end start
jmp short s
的转移范围为-128~127,IP最多向后移动127个字节;
但如果在debug中使用汇编指令jmp 2000:0100
就没有问题,如果在源程序里使用也会报错;
https://www.cnblogs.com/31415926535x/p/10187942.html
(end)