被这个汇编代码弄糊涂了
Confused by this assembly code
我试图更好地理解汇编,所以当我调试代码时,我一直在关注CDB的汇编输出。我的平台是搭载Windows 7的英特尔至强处理器。
下面的c++代码:
int main()
{
int a = 30;
int b = 0;
b = ++a;
return 0;
}
为带有自增操作符的行生成以下程序集:
b = ++a;
0x13f441023 <+0x0013> mov eax,dword ptr [rsp]
0x13f441026 <+0x0016> inc eax
0x13f441028 <+0x0018> mov dword ptr [rsp],eax //Move eax to some memory address
0x13f44102b <+0x001b> mov eax,dword ptr [rsp] //Move it back to eax?
0x13f44102e <+0x001e> mov dword ptr [rsp+4],eax
我的问题是,将eax
中的值移动到内存中的目的是什么,然后立即将相同的值移动回eax
,如注释所示?这是为了线程安全,还是只是调试构建的一些工件?
编译器最初使用静态单赋值(SSA)将指令转换为汇编,这意味着每个操作都获得一个临时值来存储其结果。只有在之后的后端阶段,这些值才会根据您的目标机器转换为机器寄存器,如果有必要(显式要求或由于缺乏寄存器而溢出),可能还会转换为内存位置。
在这两个阶段之间,优化器可以消除部分值,但最初++a是一个操作,将a(后增量)赋值给b是第二个操作。由于a和b都是局部变量,它们将被存储在堆栈中(并且必须在堆栈中可见,例如,如果您使用调试器步进),a将驻留在[rsp]中,b驻留在[rsp+4]中。
所以你的编译器,在某些时候,可能有(在一些中间表示):
value1 = a
value2 = value1 + 1
a = value2 //self increment
b = a
或者类似的东西。A和b必须驻留在内存中,但操作通常是在寄存器上完成的,所以一开始编译器会这样做-
value1 = a
value2 = value1 + 1
0x13f441023 <+0x0013> mov eax,dword ptr [rsp]
0x13f441026 <+0x0016> inc eax
a = value2
0x13f441028 <+0x0018> mov dword ptr [rsp],eax
b = a
0x13f44102b <+0x001b> mov eax,dword ptr [rsp]
0x13f44102e <+0x001e> mov dword ptr [rsp+4],eax
请注意,中间值保存在寄存器中——在正常编译中,它们可能会被一次优化传递(在分配寄存器和生成代码之前)完全消除。
只是调试构建的一些工件?
是的,只是调试构建的一些工件(实际上来自未优化的构建)
相关文章:
- 任何人都可以弄清楚这段代码如何显示运行错误?它打印无限时间 -1 以及正确答案
- 试图弄清楚我需要做哪些更改才能使代码正常工作.使用Visual Studio
- 被这种语法弄糊涂了
- 弄清楚这段代码是怎么回事(递归下降案例研究)
- 我无法弄清楚我的代码未显示预期结果的问题
- 我无法弄清楚我的代码出了什么问题
- 堆排序,我无法弄清楚我的代码出了什么问题,输出顺序不正确
- 我需要帮助弄清楚如何将getline纳入PresentStringPrompt,以摆脱重复的代码
- Visual Studio 2019不活跃的代码没有弄清楚
- 为什么此串行/调制解调器代码弄乱了我的终端显示
- 无法弄清楚为什么这个Arduino代码不起作用?
- 我需要帮助弄清楚为什么此C 程序不会使用GNU CC编译器在代码块中构建和运行
- 获取线函数弄乱代码
- 被所有关于向ec2linux添加新glib版本的帖子弄糊涂了
- 被管道弄糊涂了。"cat -A"似乎过滤掉了部分输出
- 被这个汇编代码弄糊涂了
- 被lambda输出弄糊涂了
- 被增强精灵/凤凰/ c++ 11的交互弄糊涂了
- 被gprof输出弄糊涂了——调用太多
- 把自己弄糊涂了,指针对指针太多了