1.offset
伪指令由编译器识别
用法:assume cs:codesg
codeseg segment
start: mov ax,offset start;相当于mov ax,0
s:mov ax,offset s;相当于mov ax,3
codesg ends
end start
注:一条指令占三个字节如:mov ax,2 bb 0200
一条指令占二个字节如:mov ax,bx 89DB
例子:assume cs:codesg
codesg segment
s:mov ax,bx;(mov ax,bx 的机器码占两个字节)
mov si,offset s
mov di,offset s0
mov ax,cs:[si]
mov cs:[di],ax
s0:nop;(nop的机器码占一个字节)
nop
codesg ends
ends
实现的功能:把s处的代码转移到s0处
2.jmp
jmp指令要给出两种信息:
转移的距离(段间转移、段内短转移,段内近转移)
转移的目的地址
1.jmp short 标号 实现段内短转移,对ip的修改范围是:-128-127,也就是说,它向前转移时可以最多越过128个字节,向后转移可以最多越过127个字节。
如:assume cs:codesg
codesg segment
start:mova x,0
jmp short s
add ax,1
s:inc ax
codesg ends
end start
注意:jmp short s对应的机器码为EB03,并不是
先执行 mov ax,0000 EB03即向前跳3个字节,跳到076a:0008处(jmp short s在编译时算出)
2.jmp near ptr 标号。“jmp near ptr 标号”的功能为:(IP)=(IP)+16位位移
位移的范围为-32769~32767 编译时算出
3.jmp far ptr 标号 实现的是段间转移,又称为远转移。
assume cs:codesg
codesg segment
start:mov ax,0
mov bx,0
jmp far ptr s
db 256dup(0)
s:add ax,1
inc ax
codesg ends
end start
可以看到jmp far ptr直接改变cs:ip的值和near、short不同
4.jmp debug和masm模式下实现
1.jmp word ptr 内存单元地址(段内转移)
mov ax,0123
mov [0] ax
jmp [0]
执行完ip = 0123H
2.jmp dword ptr 内存单元地址(段间转移)
mov ax,0123H
mov ds:[0],ax
mov word ptr ds:[2],0
jmp dword ptr ds:[0]
该程序在masm下编译执行,debug下不行
得到结果:cs:0000 ip:0123
JCXZ的使用:
先补充个masm的知识:
start:mov ax,0123H
s:mov bx,0223H
mov ax,4c00H
int 21H
虽然没执行loop s但是s后面的内容仍然会执行
例子:利用jcxz指令,实现在内存2000H段中查找第一个值为0的字节,找到后将它的偏移地址存储在dx中
start:mov ax,2000H
mov ds,ax
mov bx,0
s:mov cl,[bx]
mov ch,0
jcxz ok //检查cx的值,为0则查找结束,跳向ok标志地址
inc bx
jmp short s //查找失败则循环继续查找
ok:mov dx,bx
mov ax,4c00H
int 21H
执行过程:从start处开始执行,继续往下执行,当执行到jcxz ok处检查cx的值是否为0;如果为0则跳到ok处,如果不为0则继续往下执行到jmp short s处,跳到s处继续从s处往下执行
LOOP的使用:
例:
start:mov ax,2000H
mov ds,ax
mov bx,0
s:mov cl,[bx]
mov ch,0
inc ax
inc bx
loop s
ok:dec bx
mov dx,bx
mov ax,4c00H
int 21H