尝试从 g++ 理解简单的反汇编代码
Trying to understand simple disassembled code from g++
我仍在努力使用g++内联汇编器,并试图了解如何使用它。
我从这里改编了一段代码:http://asm.sourceforge.net/articles/linasm.html(引自 gcc 信息文件中的"带有 C 表达式操作数的汇编程序指令"部分)
static inline uint32_t sum0() {
uint32_t foo = 1, bar=2;
uint32_t ret;
__asm__ __volatile__ (
"add %%ebx,%%eax"
: "=eax"(ret) // ouput
: "eax"(foo), "ebx"(bar) // input
: "eax" // modify
);
return ret;
}
我编译了禁用优化:
g++ -Og -O0 inline1.cpp -o test
反汇编的代码让我感到困惑:
(gdb) disassemble sum0
Dump of assembler code for function sum0():
0x00000000000009de <+0>: push %rbp ;prologue...
0x00000000000009df <+1>: mov %rsp,%rbp ;prologue...
0x00000000000009e2 <+4>: movl $0x1,-0xc(%rbp) ;initialize foo
0x00000000000009e9 <+11>: movl $0x2,-0x8(%rbp) ;initialize bar
0x00000000000009f0 <+18>: mov -0xc(%rbp),%edx ;
0x00000000000009f3 <+21>: mov -0x8(%rbp),%ecx ;
0x00000000000009f6 <+24>: mov %edx,-0x14(%rbp) ; This is unexpected
0x00000000000009f9 <+27>: movd -0x14(%rbp),%xmm1 ; why moving variables
0x00000000000009fe <+32>: mov %ecx,-0x14(%rbp) ; to extended registers?
0x0000000000000a01 <+35>: movd -0x14(%rbp),%xmm2 ;
0x0000000000000a06 <+40>: add %ebx,%eax ; add (as expected)
0x0000000000000a08 <+42>: movd %xmm0,%edx ; copying the wrong result to ret
0x0000000000000a0c <+46>: mov %edx,-0x4(%rbp) ; " " " " " "
0x0000000000000a0f <+49>: mov -0x4(%rbp),%eax ; " " " " " "
0x0000000000000a12 <+52>: pop %rbp ;
0x0000000000000a13 <+53>: retq
End of assembler dump.
正如预期的那样,sum0() 函数返回错误的值。
有什么想法吗?这是怎么回事?如何做到正确?
--编辑--根据@MarcGlisse评论,我尝试了:
static inline uint32_t sum0() {
uint32_t foo = 1, bar=2;
uint32_t ret;
__asm__ __volatile__ (
"add %%ebx,%%eax"
: "=a"(ret) // ouput
: "a"(foo), "b"(bar) // input
: "eax" // modify
);
return ret;
}
似乎我一直遵循的教程具有误导性。输出/输入字段中的"EAX"不是指寄存器本身,而是缩写表上的 e,a,x 缩写。
无论如何,我仍然没有做对。上面的代码导致编译错误:"asm"操作数具有不可能的约束。
我不明白为什么。
x86 的扩展内联程序集约束列在官方文档中。
完整的文档也值得一读。
如您所见,约束都是单个字母。
约束 "eax" fo foo
指定了三个约束:
一个
A 寄存器。x
任何 SSE 寄存器。e
32 位有符号整数常量,或 ...
由于您告诉 GCC eax
被破坏,因此它无法将输入操作数放在那里,它会选择xmm0
。
当编译器选择要用于表示输入操作数的寄存器时,它不使用任何被破坏的寄存器
适当的约束只是"a"。
您需要从碎屑中删除eax
(顺便说一下,由于上位归零,它应该rax
)(并添加"cc")。
相关文章:
- Capstone cs_disasm仅反汇编一小部分代码
- 如何使用 objdump 反汇编 OpenJDK(bin/java)
- 在 GDB - C++ 中反汇编重载成员函数
- 尝试从 g++ 理解简单的反汇编代码
- 反汇编中的硬编码地址
- assert()函数未在反汇编中显示
- 反汇编的 exe 文件包含比源代码多得多的代码
- 分析崩溃的反汇编 C++ 代码
- 如何通过反汇编从C++函数获取"lea"指令?
- 如何在gdb中读取内存地址以进行i7处理器代码的反汇编
- arm汇编代码-理解cpp源代码的反汇编
- 研究一个简单的代码反汇编输出和内存映射
- Visual Studio Express 2010 C++反汇编调试
- 我的函数及其参数在反汇编视觉 c++ 中的名称
- 一些反汇编c++代码我很困惑
- 反汇编函数参数(无符号__int8)大海捞针[19] << 8)
- 使用虚继承的简单程序汇编输出
- 关于反汇编输出的问题
- 编译c++代码成汇编,然后反汇编
- 在c++中执行一个简单的汇编代码,而不是在函数中