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 进行反汇编查看。
|
//db 100 dup (0 , 0 , 0 ) |
//100 dup (0b8h , 0 , 0 ) // 拷贝的是指令代码 |
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 进行反汇编查看。
|
// EB09,09是编译到后面标号s处再从新填写disp | // 目标地址的偏移都是0137,disp第一个时0134,第二个是0131; |