Chr*_*Man 1 x86 assembly x86-64 gnu-assembler clang
我如何跳转到 intel 汇编语法(x32 和 x64)中的已知内存地址。
我想我已经掌握了 64 位语法。例如,如果在 x64 中我想跳转到位于 的代码0x75767并且我位于0000,我会这样做:
0000: FF 25 01 00 00 00 jmp QWORD PTR [rip+0x75761]
Run Code Online (Sandbox Code Playgroud)
^ 正确吗?我想我可以使用 objdump 将这些字节分解为 x32 指令,objdump.exe -D -Mintel,i386 -b binary -m i386 test.bin结果是:
jmp DWORD PTR 0x75761
Run Code Online (Sandbox Code Playgroud)
然后只需使用clang++.exe -masm=intel -m32 -c test.o将此指令转换为 x32 字节即可,但它显示:
error: invalid operand for instruction
jmp DWORD PTR 0x75761
^
Run Code Online (Sandbox Code Playgroud)
我想避免写入任何寄存器。
我的 x64 jmp 指令正确吗?
我如何在 x32 中完成类似的事情?假设在 x32 中我需要跳转到0x400107并且我在0x400000
我正在调整 Windows 上的运行进程内存。如果我的问题有不准确的地方,请原谅我,我正在学习。
目前尚不清楚您是否需要汇编代码或机器代码。如果要跳转到绝对地址,则在 64 位模式下使用嵌入式指针寻址 rip 相对:
jmp [rip+foo]
foo: .quad target_address
Run Code Online (Sandbox Code Playgroud)
机器码:(ff 25 00 00 00 00 xx xx xx xx xx xx xx xx最后8个字节为目标绝对地址)。
前 6 个是指令,其中 2 个字节编码操作jmp码 + modrm,后面的 4 个字节是rel32=0,因此加载地址是整个指令末尾之后的 0 个字节。
或者,如果您可以腾出一个寄存器,mov r11, OFFSET target_address/ jmp r11,或选择任何您可以修改的寄存器。这通常比从代码加载数据有更好的性能,代码加载通常在 L1d 缓存或 L1dTLB 中不会很热(但可能在 L2 或 L2TLB 中)。通常,您希望将常量与其他常量一起放在其他.quad地方只读数据,如果方便的话。)
在 32 位代码中,如果您不担心分支预测,则可以使用push+技巧:ret
push offset target_address
ret
Run Code Online (Sandbox Code Playgroud)
机器代码:68 xx xx xx xx c3
如果你可以计算相对地址,你当然可以使用一个普通的地址jmp,e9 xx xx xx xx最后 4 个字节是跳转的距离(从指令后面的字节开始计算,通常会继续执行)。
如果性能确实很重要,那么mov eax, offset target_address/jmp eax是一种非常标准的方式。(如果此时您不需要它的值,则任何寄存器都可以工作。)