汇编语⾔第九章转移指令的原理
转移指令:
可以修改IP,或者同时修改CS和IP的指令称为转移指令。
只修改IP时,称为段内转移,段内转移根据IP的修改范围⼜分为短转移(short)和近转移(near);短转移IP的修改范围为8位补码表⽰的范围:-128~127.近转移IP的修改范围为16位补码表⽰的范围:-32768~32767(向前为负,向后为正)
同时修改IP和CS时,称为段间转移,⼜称远转移(far)。
转移指令分类:
1. ⽆条件转移指令,jmp,其他转移指令⼤多可以基于jmp写出
2. 有条件转移指令,jcxz
3. 循环转移指令,loop
4. 过程
5. 中断
操作符offset:
offset的功能是获取标号的偏移地址EA,标号指的是s、start、data⼀类的名称。
⽆条件转移指令jmp:
jmp给出的两种信息:
转移的⽬的地址,由标号给出
转移的距离(段间转移,段内短转移short,段内近转移near)
1. 短转移、近转移jmp指令
jmp short 标号(该指令本⾝占两个字节)翻译成机器码为 EBXX,XX为转移位移量的补码表⽰,向前为负向后为正。没有表达出绝对的⽬的地址,只给出了相对的位移。
位移量XX = 标号处的地址 - jmp指令后⼀个字节的地址,short指明位移量为8位。(IP)=(IP)+ XX()8位位移
类似的还有 jmp near ptr 标号(也可写成jmp s 省略near ptr)(该指令本⾝占三个字节)翻译成机器码为 E9XXXX  其位移量⽤两个字节表⽰,ptr可以看作是长度声明。(IP)=(IP) +  XXXX  16位位移
offset指令是什么意思
2.远转移jmp指令
jmp far ptr 标号(该指令本⾝占五个字节)翻译成机器码为 EAXXXX YYYY,XXXX为偏移地址,前两个X为低位,后两个X为⾼位;YYYY 为段地址,前两个Y为低位,后两个Y为⾼位。
向前转移:
编译器中有⼀个地址计数器AC,编译器读到标号s时记下AC的值as,读到jmp时记下AC的值aj,再⽤aj - ac算出位移量disp
-128 < disp < 127 时,近转移、远转移统统转化成短转移,机器码为EB disp(占两个字节)
disp超出上述范围,得⽤16位补码表⽰时,短转移将产⽣编译错误,近转移和远转移正常执⾏
向后转移:
向后转移时,编译器先读到jmp指令,记下aj,但没有as,⼀时⽆法计算位移量disp,这时会对jmp指令进⾏⼀个预处理,预处理不管转移类型,统⼀当作短转移,但预留的空间不同
对于短转移,编译器⽣成EB和1个nop指令,相当于预留⼀字节,⽤于存放8位disp
对于近转移,编译器⽣成EB和2个nop指令,相当于预留两字节,⽤于存放16位disp
对于远转移,编译器⽣成EB和4个nop指令,相当于预留四字节,⽤于存放段地址和偏移地址
当编译器往后读到as时,计算disp = as - aj
-128 < disp < 127 时,近转移、远转移统统转化成短转移,机器码为EB disp,多余的预留空间闲置
disp超出上述范围,得⽤16位补码表⽰时,短转移将产⽣编译错误,近转移和远转移正常执⾏,在预留的位置添上相应代码即可
3.转移信息在寄存器或者内存中的jmp指令
jmp 16位寄存器(只能是16位寄存器,因为相当于mov ip ,res,寄存器位数要对应)。在Debug中还可以使⽤ jmp XXXX:YYYY格式直接修改CS和IP,但编译器⽆法识别。
jmp word ptr 内存单元地址执⾏后,(IP) = (内存单元地址),指的是内存单元地址中的内容赋给IP,(两个字节)例如对应内容为0123H,那么IP = 0123H。只改变IP,是段内转移。
jmp dword ptr 内存单元地址执⾏后,(IP)= (内存单元地址)(CS)= (内存单元地址+2),都是赋给其中的内容,(四个字节)低地址赋给IP,⾼地址赋给CS。改变IP和CS,是段间转移。
jcxz条件转移指令:
jcxz  标号(如果(cx)=0,执⾏跳转指令,(cx)不为0时,跳过该指令)所有的条件转移指令都是短转移类型,机器码中包含的是8位位移。⽤C语⾔等价描述为 if ((cx) == 0)  jmp short 标号
loop循环指令:
loop 标号(先执⾏(cx)= (cx) - 1 ,再判断如果(cx) ≠0,修改IP转移到标号处执⾏,(CX)= 0时跳过指令往下执⾏)所有的循环指令都是短转移类型。⽤C语⾔等价描述为 (cx)--; if ((cx) != 0) jmp short 标号