修改IP或者同时修改CS和IP的指令叫做转移指令。
offset操作符:由编译器处理,可以取得标号(start,s…)的偏移地址。 jmp指令:无条件转移,只可以修改IP或同时修改CS和IP。使用时需要给出转移的目的地址以及转移的距离(段间转移、段内短转移、段内近转移)。
jmp的不同应用格式: (1)转移地址在指令中 jmp short 标号(转到标号处执行指令) 段内短转移,对IP的修改范围是-128-127,即向前最多128字节,向后最多127字节。short表明进行的是短转移。标号是代码段中的标号,指明目的地址。 CPU在执行jmp指令的时候并不知道目的地址(jmp指令对应的机器码中没有描述目的地址),但是知道相对于当前IP要转移的位移(机器码中有描述)。具体如下: jmp short 标号 的功能为(IP) = (IP) + 8位位移。 8位位移=标号处地址-jmp指令后第一个字节的地址。 short指明为8位位移(-128-127,用补码表示)(补码知识参见最后)。 8位位移由编译器在编译时算出。 jmp near ptr 标号 段内近转移。(IP) = (IP)+16位位移。 16位位移=标号处地址-jmp指令后第一个字节的地址。 near ptr指明为16位位移(-32768-32767,用补码表示)(补码知识参见最后)。 16位位移由编译器在编译时算出。 jmp far ptr 标号 段间转移(远转移)。 (CS) = 标号所在段的段地址;(IP) = 标号在段中的偏移地址。 far ptr 指明用标号所在的段地址和偏移地址修改CS和IP。 该jmp指令对应机器码举例:EA0B01BD0B,可知转移的目的地址为:0BBD:010B。
(2)转移地址在寄存器中 jmp 16位reg 修改IP。(IP) = (16位reg)
(3)转移地址在内存中 jmp word ptr 内存单元地址(段内转移) 在内存单元地址处取出一个字,作为转移的目的偏移地址。 内存单元地址可以用任意寻址方式表示。 jmp dword ptr 内存单元地址(段间转移) 在内存单元地址处取出两个字,高地址处的字是转移的目的段地址,低地址处的字是转移的目的偏移地址。(CS) = (内存单元地址+2), (IP) = (内存单元地址)
补码 以8位二进制数举例,无符号数可以为00000000-11111111,即0~255. 对于有符号数,采用补码方案: (1)最高位为1,表示负数。 (2)正数的补码取反加1后,为其对应负数的补码。负数补码取反加1后,为其对应绝对值。 1的补码为00000001b,取反后加1,11111111b,表示-1. -1的补码为11111111b,取反后加1,00000001b,表示1. 补码练习: 11010101b表示的数据是()16。 -2BH -20的补码是()。11101100b 10000000b表示的数据是(). -128 8位补码表示数的范围是-128-127. 有符号数的补码运算,运算后结果依然满足补码规则。
jcxz指令:有条件转移指令。均为短转移-128-127。对应机器码中为转移的位移。 jcxz 标号 (如果(cx)=0,)转移到标号处执行 当cx != 0时,什么也不做。 可以将 jcxz 标号 看做 if((cx) == 0) jmp short 标号;
mov cl,[bx] mov ch,0 jcxz ok inc bx
loop指令:短转移指令-128-127,对应机器码中为转移的位移。 loop 标号 先执行(cx)=(cx)-1 如果(cx)!=0,(IP)=(IP)+8位位移 如果(cx)=0, 什么也不做。 可以将 loop 标号 看做 (cx)–; if((cx)!=0) jmp short 标号;
inc cx
程序可以正确返回,程序的入口为mov ax, 0,注意到指令jmp short s1占2字节,于是指令mov di, offset s将s的偏移地址传送到寄存器DI,mov si, offset s2将s2的偏移地址传送到SI,然后再通过通用寄存器ax做中转将s2处的指令复制到s处,最后再跳转至s处执行复制过来的指令。 注意jmp short s1是相对跳转,其直接修改IP寄存器,从s2到s1共有8个字节的偏移,实际上 jmp short s1等价于(ip)=(ip)-8,通过Debug可知第一个nop指令的偏移地址为8,所以再执行了复制过的指令后,IP将指向0,程序按照顺序执行mov ax, 4c00h和int 21h,正确返回。
