转移指令的原理
①:可以修改IP,或同时修改CS和IP的指令称为转移指令。
8086CPU的转移行为有以下几类。
只修改IP时,称为段内转移,比如:jmp ax。
同时修改CS和IP时,称为段间转移,比如:jmp 1000:0.
由于转移指令对IP的修改范围不同,段内转移又分为:短转移和近转移。
短转移IP的修改范围为-128-127.
近转移IP的修改范围为-32768-32767.
8086CPU的转移指令分为以下几类:
1.无条件转移指令
2.条件转移指令
3.循环指令 loop
4.过程
5.中断
②:操作符offset在汇编语言中是由编译器处理的符号,它的功能是取得符号的偏移地址。
codesg segment
start:mov ax,offset start ;相当于 mov ax,0
s:mox ax,offset s ;相当于 mov ax,3
codesg ends
③:jmp short 标号(转到标号处执行指令)
这种格式的jmp指令实现的是段内短转移,它对IP的修改范围为-128~127。
CPU在执行jmp指令的时候并不需要转移的目的地址,而是通过转移位移。
实际上 “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位位移由编译程序在编译时算出。
jmp far ptr 标号 实现的是段间转移,又称为远转移。汇编代码是包括转移的目的地址的。
jmp 16位reg 功能: (IP) = (16位reg)
转移地址在内存中的jmp指令有两种格式:
1.jmp word ptr 内存单元地址(段内转移)
功能:从内存单元地址处开始存放着一个字,是转移的目的偏移地址。
2.jmp dword ptr 内存单元地址(段间转移)
功能:从内存单元地址处开始存放着两个字,高地址处的字是转移的目的段地址,低地址处是转移的目的偏移地址。
(CS) = (内存单元地址+2)
(IP) = (内存单元地址)
④:jcxz指令为有条件转移指令,所有的有条件转移指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围都为-128-127.
指令格式:jcxz标号(如果(cx)=0,转移到标号处执行。)
操作:当(cx)=0时,(IP)=(IP)+8位位移;
8位位移=标号处的地址-jmp指令后的第一个字节的地址;
8位位移的范围-128-127,用补码表示;
8位位移由编译程序在编译时算出。
功能:
if((cx)==0) jmp short 标号
⑤:loop指令为循环指令,所有的循环指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围都为-128-127.
指令格式:loop标号((cx)=(cx)-1,如果(cx)!=0,转移到标号处执行。)
操作:
1.(cx)=(cx)-1;
2.如果(cx)!=0,(IP)=(IP)+8位位移;
8位位移=标号处的地址-loop指令后的第一个字节的地址;
8位位移的范围-128-127,用补码表示;
8位位移由编译程序在编译时算出。
如果(cx)=0,什么也不做(程序向下执行)
功能:
(cx)—;
if((cx)!=0) jmp short 标号;
CALL和RET指令
①:ret指令用栈中的数据,修改IP的内容,从而实现近转移;
retf指令用栈中的数据,修改CS和IP的内容,从而实现远转移。
CPU执行ret指令时,相当于进行:
pop IP
CPU执行retf指令时,相当于进行:
pop IP
pop CS
②:CPU执行call指令时,进行两步操作:
1.将当前的IP或CS和IP压入栈中;
2.转移。
相当于:
push IP
jmp near ptr 标号
call far ptr 标号 实现的是段间转移。
相当于:
push CS
push IP
jmp far ptr 标号
call 16 位reg 相当于:
push IP
jmp 16位reg
call word ptr 内存单元地址:
push IP
jmp word ptr 内存单元地址
call dword ptr 内存单元地址:
push CS
push IP
jmp dword ptr 内存单元地址
③:mul是乘法指令
1.两个相乘的数:两个相乘的数,要么都是8位,要么都是16位。如果是8位,一个默认放在AL中,另一个放在8位reg或内存单元中;如果是16位,一个默认放在AX中;另一个放在16位reg或内存单元中。
2.结果:如果是8位乘法,结果默认放在AX中;如果是16位乘法,结果高位默认在DX中存放,低位在AX中存放。
mul byte ptr ds:[0]
含义:(ax) = (al)*((ds)*16+0)
mul word ptr [bx+si+8]
含义:(ax) = (ax)*((ds)*16+(si)+8) 结果的低16位
(dx) = (ax)*((ds)*16+(si)+8) 结果的高16位
④:定义以0结尾的字符串
db ‘string’,0
解决寄存器冲突的方法:
在子程序的开始将子程序中所有用到的寄存器中的内容都保存起来,在子程序返回前再恢复,注意寄存器入栈和出栈的顺序!
BY:AloneMonkey