在程序集中考虑一个简单的跳转指令(jmp),其中destination是一个预定义的标签。
jmp destination
根据Kip Irvine的“x86处理器的汇编语言”,当CPU执行无条件传输时, destination 的偏移量将移入指令指针。
有人可以解释一下,因为我认为我们要跳转的地址必须移到指令指针中吗?
答案 0 :(得分:4)
我找到了你正在谈论的那段话:
4.5.1 JMP指令
JMP指令导致无条件传输到目标,由汇编程序转换为偏移量的代码标签标识。语法是
JMP目的地
当CPU执行无条件传输时,将目标偏移量移入指令指针,导致执行在新位置继续。
你的困惑是可以理解的;这个解释得很差。
首先,如果指令显示jmp destination
,则它将指令指针设置为destination
。你是对的。
但是指令行为与指令编码混淆。
表单jmp address
的说明使用x86中的相对偏移进行编码。偏移量相对于 jmp
指令后的地址。
这可以编码为EB
后跟有符号字节偏移或E9
后跟有符号双字偏移。 (整数在x86中为little endian)
例如,
00010000: EB 01 CC 90
反汇编
loc_10000:
jmp loc_10003 ; EB 01
int3 ; CC
loc_10003:
nop ; 90
和
00010000: E9 01 00 00 00 CC 90
反汇编
loc_10000:
jmp loc_10006 ; E9 01 00 00 00
int3 ; CC
loc_10006:
nop ; 90
请注意,这意味着当位于不同的地址时,以相同方式编写的指令可能具有不同的编码。例如,
00010000: EB 02 EB 00 CC EB FD EB FB
反汇编
loc_10000:
jmp loc_10004 ; EB 02
jmp loc_10004 ; EB 00
loc_10004:
int3 ; CC
jmp loc_10004 ; EB FD (FD == -3)
jmp loc_10004 ; EB FB (FB == -5)
旁注:jmp
指令有几种不同的形式,但您所说的类型只能用相对偏移进行编码。
无论如何,作者所说的是,对于汇编程序为jmp destination
之类的指令生成机器代码,它必须将destination
转换为相对于{{{}的末尾的字节偏移量。 1}}指令。但是,大多数情况下,您无需担心此过程。您只需在程序集中定义标签并编写jmp
,汇编程序就会为您处理所有事情。
答案 1 :(得分:1)
考虑这个假机器
address: bytes: comment:
0x0004 01 20 00 ; jmp destination ; here ip = 0x0004
0x0007 ?? repeated 0x19 times
destination:
0x0020 02 ; hlt ; here ip = 0x0020
从这个来源编译:
.code
org 0x0004
jmp destination
org 0x0020
destination:
hlt
因此,destination
这里的符号表示0x0020
部分中的绝对地址.code
(我不会给出任何特殊含义,但您可以想象任何复杂的结构,因为示例请参见x86的16b模式中的段寄存器。
然后,如果代码为0x01 jmp
的指令“接近”,则只使用该绝对地址的偏移量,在这个简单的假例子中为0x0020。
您的CPU上仍然可以有jmp
的其他变体,例如“relative”0x03 jmp rel8
能够从当前ip
跳转-128 .. + 127个字节,或者“远” “0x04 jmp bank/segment:offset
,不仅会设置ip
,还会设置一些银行/分段机制。
因此,“偏移”一词指向segment:offset
寻址的时代,其中x86上的完整指令指针为cs:ip
,而不仅仅是ip
。 (cs =代码段)
在现代32 / 64b x86操作系统中,您通常不需要触摸cs
,只能使用32 / 64b平面虚拟内存映射中的偏移,然后“地址”与“偏移”具有相同的含义地址”。