body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;} th{border: 1px solid gray; padding: 4px; background-color: #DDD;} td{border: 1px solid gray; padding: 4px;} tr:nth-child(2n){background-color: #f8f8f8;}
1、向前转移
s: : : : jmp s ( jmp short s、jmp near ptr s、jmp far ptr s ) |
编译器中有一个地址计数器(AC ) ,编译器在编译程序过程中,每读到一个字节AC就加一。当编译器遇到一些伪操作的时候,也会根据具体情况使AC增加,如db、dw 等。
在向前转移时,编译器可以在读到标号s 后记下AC 的值as ,在读到jmp … s 后记下AC的值aj 。编译器可以用as – aj 算出位移量disp 。
此时,编译器作如下处理:
(1)如果disp ∈[128,127 ],则不管汇编指令格式是: jmp s jmp short s jmp near ptr s jmp far ptr s 中的哪一种,都将它转变为jmp short s 所对应的机器码。 jmp sbort s 所对应的机器码格式为:EB disp(占两个字节) 编译,连接以下程序,用Debug 进行反汇编查看。 assume cs : code code segment s: jmp s jmp short s jmp near ptr s jmp far ptr s code ends end s | (2)如果disp∈[32765,32767],则: 对于jmp short s 将产生编译错误; 对于jmp s、jmp near ptr s 将产生 jmp near ptr s 所对应的机器码; jmp near ptr s 所对应的机器码格式为;E9 disp (占3 个字节) 对于jmp far ptr s 将产生相应的编码; jmp far ptr s 所对应的机器码格式为:EA 偏移地址 : 段地址(占5 个字节) 编译,连接以一下程序: assume cs : code code segment s: db 100 dup (0b8h , 0 , 0 ) ; db 100 dup (0 , 0 , 0 ) ;jmp short s ; 超过short能表示的8位范围 start: jmp s jmp near ptr s jmp far ptr s code ends end s 编译中将产生错误,错误是由jmp short s 引起的,去掉jmp short s 后再编译就可通过。用Debug 进行反汇编查看。 |
2、向后转移
jmp s (jmp short s、jmp near ptr s、jmp far ptr s) : : s: : |
在这种情况下,编译器先读到jmp … s 指令。由于它还没有读到标号 s ,所以此时还不能确定标号s 处的AC 值。也就是说,编译器不能确定位移量disp 的大小。此时,编译器将 jmp … s 指令都当作jmp short s 来读取,记下jmp … s 指令的位置和AC的值aj ,并作如下处理:
对于jmp short s ,编译器生成EB 和1 个nop 指令(相当于预留1 个字节的空间,存放8位disp ); 对于jmp s 和jmp near ptr s ,编译器生成EB 和两个nop指令(相当于预留两个字节的空问,存放16 位disp ) ; 对十jmp far ptr s ,编译器生成EB 和4 个nop 指令(相当于预留4 个字节的空间,存放段地址和偏移地址)。 |
做完以上处理后,编译器继续工作,当向后读到标号s 时,记下AC 的值as ,并计算出转移的位移量:disp = as – aj 。
此时,编译器作如下处理:
(1)当disp ∈[ –128 ,127]时,不管指令格式是: jmp short s jmp s jmp near ptr s jmp far ptr s 中的哪一种,都在前面记下的jmp … s 指令位置处添上jmp short s 对应的机器码(格式为:EB disp)。 注意:此时,对于jmp s 和jmp near ptr s 格式,在机器码EB disp后还有1 条nop 指令;对于jmp far ptr s 格式,在机器码 EB disp 后还有3 条nop 指令。 编译,连接以下程序,用Debug 进行反汇编查看。 assume cs : code code segment begin: jmp short s jmp s jmp near ptr s jmp far ptr s s: mov ax,0 code ends end begin | (2)当disp ∈[ –32768 ,32767]时,则: 对于jmp short s ,将产生编译错误; 对于jmp s 、jmp near ptr s ,在前面记下的jmp … s 指令位置处添上 jmp near ptr s 所对应的机器码(格式为:E9 disp)。 对于 jmp far ptr s 在前面记下的jmp … s 指令位置处添上对应的代码。 编译,连接以下程序: assume cs : code code segment begin: ;jmp short s ; 超过short能表示的8位范围 jmp s jmp near ptr s jmp far ptr s db 100 dup ( 0b8h , 0 , 0 ) s: mov ax,2 code ends end begin 在编译中将产生错误,错误是由jmp short s 引起的,去掉jmp short s 后再编译就可通过。用Debug 进行反汇编查看。 |