Assembly 在x86中编码JMP(64位模式)

Assembly 在x86中编码JMP(64位模式),assembly,x86,x86-64,instruction-set,Assembly,X86,X86 64,Instruction Set,我熟悉r/m8、r/m16、imm16等,但如何对m16:16、m16:32和m16:64进行编码?这些都在JMP和CALL指令中 m16:16是地址位置吗?还是像一个直接地址?任何帮助都将不胜感激 “编码”通常指机器代码字节。但我想你是在问汇编程序语法,因为英特尔的手册对机器代码很清楚。(有关条目的格式以及内容的含义,请参阅条目或的其他部分。) jmp m16:64是一个内存间接跳转,带有一个新的RIP和CS值(按照这个顺序,因为x86是小端) 就像内存间接近跳转一样,只需提供一个寻址模式,

我熟悉r/m8、r/m16、imm16等,但如何对m16:16、m16:32和m16:64进行编码?这些都在JMP和CALL指令中

m16:16是地址位置吗?还是像一个直接地址?任何帮助都将不胜感激

“编码”通常指机器代码字节。但我想你是在问汇编程序语法,因为英特尔的手册对机器代码很清楚。(有关条目的格式以及内容的含义,请参阅条目或的其他部分。)


jmp m16:64
是一个内存间接跳转,带有一个新的RIP和CS值(按照这个顺序,因为x86是小端)

就像内存间接近跳转一样,只需提供一个寻址模式,CPU就会从那里加载内存操作数。但它是一个10字节的内存操作数,而不是一个接近跳跃的8字节内存操作数

您可以使用任何寻址模式。我简单地使用了
[rdi]
。所有这些对于
callfar
/
lcall
也是一样的

NASM/YASM语法:

jmp far [rdi]
AT&T语法:

ljmp *(%rdi)
GAS
.intel\u语法noprefix
反汇编:

  400080:       ff 2f              jmp    FWORD PTR [rdi]

例如,设置CS=si和RIP=rdi

; NASM syntax
mov   [rsp], rdi
mov   [rsp+8], si     ; new CS value goes last because x86 is little-endian
jmp far  [rsp]       ; loads 10 byte from memory
push rsi
/
push rdi
/
jmp far[rsp]
,或您想要使用的任何其他内存位置


NASM认为远jmp需要一个REX.W前缀。它使用

; assembled by NASM (not YASM), disassembled with objdump -drwC -Mintel
400080:       48 ff 2f                rex.W jmp FWORD PTR [rdi]
printf'\xff\x2f'|ndisam-b64-
向我们展示了NASM的反汇编输出:

; ndisasm -b64 output thinks it's a dword (m16:16)?
00000000  FF2F              jmp dword far [rdi]
英特尔的手动输入在这一点上并不明确。它将
jmp m16:64
列为需要一个REX.W前缀,但GAS/binutils认为这是不必要的。
我认为需要一些测试;通过存储当前的CS值,我们可以非常轻松地在用户空间中进行测试


jmp-far-ptr16:64
不存在,并且
ptr16:32
ptr16:16
在64位模式下不可用。这将是一个10字节的立即(直接)绝对跳转目标。x86-64根本不能使用绝对直接跳转:无法编码新的CS或将其转换为
jmp
指令

直接近跳转使用
rel32
rel8
,当然它们不能更改CS。(这就是near的意思)

32位模式具有jmp far ptr16:32(带6字节立即数)


jmpfar
的用例并不多,尤其是在64位模式下。在内核中,您可以使用
iret
sysret
返回32位用户空间,并且通常没有其他理由切换代码段。我想您可以在内核内将内核切换到32位模式。

英特尔手册说JMP far ptr16:16和JMP far ptr16:32在64位模式下都不可用。我只是用64位让事情变得更简单。上面说m16:16、m16:32和m16:64都可以使用。。。就我所知,近跳跃不必指定偏移以外的任何内容??我该如何对CS值进行编码?你也可以用寄存器跳远吗?还是地址?所以confused@RyanBrown:右,在64位模式下,没有直接远跳。CS值不会进入指令流,而是存储在内存中,并使用内存间接跳转。像
mov[rsp]、rdi
/
mov[rsp+8]、si
/
jmp far[rsp]
来做CS=si和RIP=rdi。(没有寄存器间接跳远,因为
cs:rip
不适合单个GP寄存器)。您是对的,手册将
jmp m16:32
列为64位模式下可编码的,因此对于正常的
m16:64
,您可能确实需要REX.W。否则手册就错了。所以JMP m16:64意味着我必须使用我之前定义的标签(CS)?是否用于跳转到其他程序?该死,这太复杂了!另外,远JMP16和32使用相同的操作代码,我如何区分它们?我还有一个简短的问题。是频繁使用调用还是手动使用堆栈函数?好的,最后一个问题。。。m16:64与m16:r/m64相同吗?还是仅仅是内存地址?