- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我试图编译一个非常简单的 C 程序并将其转换为汇编语言。
我使用的是 Ubuntu,操作系统类型是 64 位。
这是C程序。
void add();
int main() {
add();
return 0;
}
.file "main1.c"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
call add
movl $0, %eax
movl %ebp, %esp
popl %ebp
ret
.size main, .-main
.ident "GCC: (Debian 4.4.5-8) 4.4.5" // this part should say Ubuntu instead of Debian
.section .note.GNU-stack,"",@progbits
.file "main0.c"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ebx
pushl %ecx
call __x86.get_pc_thunk.ax
addl $_GLOBAL_OFFSET_TABLE_, %eax
movl %eax, %ebx
call add@PLT
movl $0, %eax
popl %ecx
popl %ebx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.section
.text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
.globl __x86.get_pc_thunk.ax
.hidden __x86.get_pc_thunk.ax
.type __x86.get_pc_thunk.ax, @function
__x86.get_pc_thunk.ax:
movl (%esp), %eax
ret
.ident "GCC: (Ubuntu 6.3.0-12ubuntu2) 6.3.0 20170406"
.section .note.GNU-stack,"",@progbits
.file "main0.c"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $4, %esp
call add
movl $0, %eax
addl $4, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (Ubuntu 6.3.0-12ubuntu2) 6.3.0 20170406"
.section .note.GNU-stack,"",@progbits
最佳答案
作为一般规则,您不能期望两个不同的编译器为相同的输入生成相同的汇编代码,即使它们具有相同的版本号;他们的代码生成可以有任意数量的额外“补丁”。只要可观察到的行为是相同的,任何事情都会发生。
您还应该知道 GCC,默认情况下是 -O0
模式,故意生成不良代码。它针对调试的便利性和编译速度进行了调整,而不是为了生成代码的清晰度或效率。由 gcc -O1
生成的代码通常更容易理解。比gcc -O0
生成的代码.
您还应该知道 main
函数通常需要进行其他函数不需要的额外设置和拆卸。指令leal 4(%esp),%ecx
是额外设置的一部分。如果您只想了解与您编写的代码相对应的机器码,而不是ABI 的具体细节, 将您的测试函数命名为 main
以外的其他名称.
(正如评论中所指出的,设置代码并没有像它可能的那样紧密地调整,但这通常无关紧要,因为它在程序的生命周期中只执行一次。)
现在,回答从字面上问的问题,出现的原因
call __x86.get_pc_thunk.ax
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ebx
pushl %ecx
main
的堆栈帧和需要保存的保存寄存器。你可以忽略它。
call __x86.get_pc_thunk.bx
addl $_GLOBAL_OFFSET_TABLE_, %ebx
__x86.get_pc_thunk.bx
加载它的返回地址——这是
addl
的地址紧随其后的指令 -- 进入 EBX 寄存器。然后我们将魔法常数
_GLOBAL_OFFSET_TABLE_
的值添加到该地址。 ,在与位置无关的代码中,它是使用
_GLOBAL_OFFSET_TABLE_
的指令的地址之间的差值。和
global offset table的地址.因此,EBX 现在指向全局偏移表。
call add@PLT
add@PLT
, 表示拨打
add
,而是跳过“程序链接表”来做。 PLT 负责处理
add
的可能性。在共享库中定义,而不是在主可执行文件中定义。 PLT 中的代码使用全局偏移表,并假设您在调用 @PLT 符号之前已将 EBX 设置为指向它。这就是为什么
main
即使似乎没有人使用它,也必须设置 EBX。如果你改写了类似的东西
extern int number;
int main(void) { return number; }
call __x86.get_pc_thunk.bx
addl $_GLOBAL_OFFSET_TABLE_, %ebx
movl number@GOT(%ebx), %eax
movl (%eax), %eax
number
的地址从 GOT 中,然后我们实际上取消引用地址以获取
number
的值.
movl number(%rip), %eax
number
,而不是在 GOT 上乱搞。从程序计数器的固定偏移量开始。与 PC 相关的寻址与 x86 架构的 64 位扩展一起添加。同样,您的原始程序,在 64 位位置无关模式下,只会说
call add@PLT
__x86.get_pc_thunk.bx
之间的唯一区别和
__x86.get_pc_thunk.ax
是他们将返回地址存储在哪个寄存器中:EBX for
.bx
,EAX 为
.ax
.我也看到 GCC 生成
.cx
和
.dx
变种。这只是它想将哪个寄存器用于全局指针的问题——如果要通过 PLT 进行调用,它必须是 EBX,但如果没有,那么它可以使用任何寄存器,因此它会尝试选择一个其他任何东西都不需要的。
call 1f
1: pop %ebx
call
与
ret
配对.
关于c - 我如何摆脱调用 __x86.get_pc_thunk.ax,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50105581/
我想在不使用函数 m 中的循环的情况下加快计算并获得结果.可重现的例子: N require(rbenchmark) > benchmark(m(r, N), + m1(r, N
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 9 年前。 Improv
我正在尝试使用 Cython。我使用 setup.py 并构建,而不是让 pyximport 执行此操作。但是,每次我导入模块时,似乎都会调用 pyximport 。 Pyximport 构建失败,一
考虑两个案例 case1 和 case2 以及两个方法 method1 和 method2。假设方法 1 解决案例 1,方法 2 解决案例 2。现在,我有一个程序可能以 case1 或 case2 结
我怎样才能摆脱 CA2202 警告(CA2202:Microsoft.Usage:对象“compressedStream”可以在方法“Compression.InternalDecompress(by
我在这段代码中得到 NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE final Integer id = Ints.tryParse(idString); FailRea
我的 eclipse 中有 Java WebService 代码。我用过@WebService @Webmethod、@XmlElements、@XmlType、@XmlAccessorType 现在
在我正在编写的基于 Sprite 的游戏中,二维网格中的每个字段都包含一堆 Sprite 。大多数情况下,最重要的是最重要的。 在游戏的规则模块中,我有很多这样的代码: public boolean
在 Java 中,我必须设置一个带有值的 POJO 类。然而,要决定使用哪个 setter 函数,我必须取决于 if 条件。我当前的代码如下所示: // Code written in a funct
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭去年。 Improve this
所以我最近接触到了C++中所谓“令人厌恶的函数类型”的怪诞之处(据我所知源自这篇论文: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015
我正在研究配置 QDialog。它有几个类别(General、Appearance 等),当用户点击它们时会加载它们。每个类别都有自己的页面。这些页面本身就是独立的类(每个都有自己的 ui、cpp 和
我一直在开发 Vb.Net应用程序最近,我试图使它尽可能轻量级(即,使二进制文件尽可能小)。 我已经完成了所有琐碎的工作,但是在使用 ILDasm 浏览二进制文件时,我注意到它有一个 My names
An easy way to get rid of *everything* generated by SBT?要求一个简单的方法来清理从 sbt 生成的所有文件,但没有找到。我会要求一个艰难的。我如
如何摆脱默认的 ANTLR 识别错误? 我想用我自己的错误类而不是 ANTLR 的错误来写另一条消息。 我的意思是是否有可能扩展某些 ANTLR 错误类以显示我自己的消息? 更清楚地说,我不想在控制台
使用 woocommerce 的订单面板时,我注意到使用搜索执行了不必要的查询。这是对 Woocommerce 文件(/includes/data-stores/class-wc-order-data
我有一个包含列的大数据框,例如: ID, time, OS, IP 该数据帧的每一行对应一个条目。在某些 ID 的数据框中,存在多个条目(行)。我想摆脱那些多行(显然,对于相同的 ID,其他属性会有所
当我运行测试时,我得到如下代码: objc[8845]: GC: forcing GC OFF because OBJC_DISABLE_GC is set 它还会污染我运行的子流程的输出。我如何摆脱
在 ie8 上,状态栏下方有一个绿色进度指示器,可能表示基于某处某个静态长度值的下载进度。不幸的是,由于“现代”动态 JavaScript、ajax 调用等的性质,该指示器经常会变得困惑,并且栏保持在
我现在正在学习 MVVM,但我了解的东西很少(这里有很多但很少..): 是否每个模型都可能(通过 VM)暴露给 View 有一个 VM? 例如,如果我有一个 Contact 和 Address 实体并
我是一名优秀的程序员,十分优秀!