【问题标题】:How to force GCC to use jmp instruction instead of ret?如何强制 GCC 使用 jmp 指令而不是 ret?
【发布时间】:2017-10-09 05:20:14
【问题描述】:

我现在正在使用堆栈式协同程序进行网络编程。但是我受到了返回堆栈缓冲区无效的惩罚(见 http://www.agner.org/optimize/microarchitecture.pdf p.36),在上下文切换期间(因为我们手动更改了SP寄存器)

经过汇编语言测试,我发现jmp 指令优于ret。但是,我还有一些函数可以间接调用用 C++ 语言(由 GCC 编译)编写的上下文切换函数。我们如何在 GCC 汇编结果中使用 jmp 而不是 ret 强制这些函数返回?

一些常见但并不完美的方法:

  1. 使用内联汇编并手动将SP寄存器设置为__builtin_frame_address+2*sizeof(void*)jmp为返回地址,在ret之前?

这是一个不安全的解决方案。在 C++ 中,局部变量或正确值在 ret 指令之前被破坏。如果我们jmp,我们将省略这些说明。更糟糕的是,即使我们在C语言中,被调用者保存的寄存器也需要在ret指令之前恢复,我们也会省略这些指令。

那么我们可以做些什么强制 GCC 使用 jmp 而不是 ret 来避免上面列出的问题

【问题讨论】:

  • 总结一下:你正在与 CPU 作斗争(返回堆栈缓冲区无效),你正在与 C 和 C++ 语言作斗争(汇编中的协同程序,直接修改寄存器)和 你正在与 GCC 作战。 (试图改变生成的代码)。在这一点上,退后一步,重新考虑使用这些协同程序的决定可能是明智的。这将是一个痛苦的维护,并且随着新 CPU 的发布,您的手动优化可能会成为一种悲观。
  • 您必须编辑 GCC 的源代码并创建自己的编译器版本,该编译器使用 pop %ecx jmp *%ecx 之类的东西而不是 RET 指令。
  • @RossRidge 我只是使用 gcc -S 和 sed&awk shell 替换 ret、retq、rep ret、repz ret 和 gcc *.S 来获得结果。
  • 没有 C/C++ 语言。使用 C 或 C++。你说Some common but not perfect methods,但只列出了一种方法!

标签: c++ gcc assembly x86 inline-assembly


【解决方案1】:

使用汇编宏:

.macro ret
       pop %ecx
       jmp *%ecx
.endm

将它放在文件顶部或其他地方的内联汇编程序中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-27
    • 2017-05-15
    • 2015-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多