gpt4 book ai didi

assembly - 如何将此 ATT 程序集转换为英特尔语法?不使用寄存器跳转到非相对地址

转载 作者:行者123 更新时间:2023-12-05 02:29:34 26 4
gpt4 key购买 nike

我正在阅读这篇文章“assembly-challenge-jump-to-a-non-relative-address-without-using-registers”。

我需要完全按照他在这里的建议去做(不使用寄存器跳转到非相对地址),只是我需要用 intel 语法而不是 att 来做。

他找到的att语法的解决方案是:

jmp *0f(%eip)
0: .int 0x12345678

这在英特尔语法中会是什么样子?

最佳答案

该博客实际上建议在 32 位模式下使用 jmp *0f(%eip)。但那是错误的;在 32 位模式下没有可用的 EIP 相对寻址,因此这不是有效的 32 位汇编。它看起来像 clang 6.0 and earlier had a bug,无论如何它都会接受 jmp *0f(%eip),但输出显示它实际组装的指令是 jmp *0,即尝试加载从绝对地址 0 开始的跳转目标(不是 *0f,你放置一些数据的本地标签的地址)。这将不起作用,并且会简单地崩溃,假设第 0 页未映射,就像在正常操作系统下的情况一样。

(更一般地说,该错误似乎会导致 jmp label(%eip) 从下一条指令中获取 label 的位移,并将其用作绝对值地址,这永远不会有用。即,编码就像 EIP 相对寻址在 32 位模式下工作一样;在 64 位模式下,相同的机器代码使用这 4 个字节的机器代码作为rel32 相对位移而不是 disp32 绝对地址。但 x86-64 无法在保持向后兼容性的同时改变 32 位机器代码的工作方式。)所以作者对此有误,并且一定没有实际测试他们提出的代码。


您标记了这个 ,所以我假设您实际上对 64 位模式感兴趣。在那种情况下博客的建议

    jmp *0f(%rip)
0:
.quad 0x1234567890

有效。注意使用 64 位程序计数器 rip 和使用 .quad 来获取 64 位地址。 (这里使用eip实际上是一个有效的指令,对应于一个0x67地址大小覆盖,但是它会导致加载地址被截断为32位,这不太可能需要。)

用于 RIP 相对寻址的 Intel 语法因汇编程序而异。在 NASM 中你会写:

    jmp [rel label]
label:
dq 0x1234567890

其他汇编程序可能需要一些变化,或者默认情况下可能将 jmp [label] 汇编为 RIP-relative。查看您要使用的汇编器的手册。


如果您真的想在 32 位模式下完成此操作,那就更难了。如果您知道代码段的正确选择器(在许多操作系统上这将是一个固定值),您可以直接进行远跳转并将 6 字节段/偏移量直接编码到指令中。否则,我不会立即看到不使用寄存器或堆栈来执行此操作的方法。

当然,使用栈很简单,临时修改ESP:

push $0xdeadbeef   # push the constant
ret # pop it into EIP

您链接的博客也错了,写的是 push 0xdeadbeef,这是一个内存源操作数,从该绝对地址加载 4 个字节。

下一个例子也有问题,使用mov %eax,0xdeadbeef(将EAX存储到绝对地址),然后是jmp %eax(GAS汇编为jmp *%eax,警告您关于间接跳转缺少的 *

他们似乎习惯了 Intel 语法; .intel_syntax noprefix 将避免转换为 AT&T。该博客引用了一个 SO question they asked,其中出现了相同的示例。 @fuz 的回答确实纠正了 AT&T 的语法。

关于assembly - 如何将此 ATT 程序集转换为英特尔语法?不使用寄存器跳转到非相对地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72135694/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com