在编写一些C代码时,我决定将它编译成汇编并阅读它 - 我只是一点点,不时这样做 - 这是一种练习让我每次都在思考机器在做什么我在C中写了一个声明。
无论如何,我在C
中写了这两行asm(";move old_string[i] to new_string[x]");
new_string[x] = old_string[i];
asm(";shift old_string[i+1] into new_string[x]");
new_string[x] |= old_string[i + 1] << 8;
(old_string
是char
的数组,new_string
是unsigned short
的数组,所以给定两个字符42和43,这将把4342放入{ {1}})
其中产生了以下输出:
new_string[x]
(我正在自己评论,所以我可以关注正在发生的事情)。 我用-O3编译它,所以我也可以看看编译器如何优化某些结构。无论如何,我确信这可能很简单,但这是我没有得到的:
第一部分从#move old_string[i] to new_string[x]
movl -20(%ebp), %esi #put address of first char of old_string in esi
movsbw (%edi,%esi),%dx #put first char into dx
movw %dx, (%ecx,%ebx,2) #put first char into new_string
#shift old_string[i+1] into new_string[x]
movsbl 1(%esi,%edi),%eax #put old_string[i+1] into eax
sall $8, %eax #shift it left by 8 bits
orl %edx, %eax #or edx into it
movw %ax, (%ecx,%ebx,2) #?
复制char
,然后将其移动(从old_string[i]
)到dx
。然后在下一部分中,复制(%ecx,%ebx)
,将其移动或移动,然后将其放入old_string[i+1]
的相同位置。它将两个16位值放在同一个地方?这不会起作用吗?
此外,它会将ax
转换为old_string[i+1]
的高阶双字,然后将eax
(edx
}转移到其中......然后将{{1}进入记忆! new_string[x]
不会只包含ax
中已有的内容吗?所以它将同样的东西保存在内存中的同一个地方两次?
有什么我想念的吗?另外,我很确定编译程序的其余部分与这个片段无关......我在前后阅读过,找到每个数组和不同变量的存储位置,以及寄存器的值在达到该代码时会发生这种情况 - 我认为这是对于这些C行而言至关重要的那一部分。
- 哦,结果是GNU汇编注释以#。
开头答案 0 :(得分:1)
好的,毕竟这很简单。 我用笔和纸计算出来,写下每一步,它对每个寄存器做了什么,然后写下每个寄存器的内容给出初始起始值......
让我觉得它是使用32位和16位寄存器来处理16位和8位数据类型...... 这就是我的想法:
我不明白为什么它将它写入内存两次,或者为什么它使用32位寄存器(实际上,我的猜测是32位处理器使用32位值比使用32位值更快有8位和16位值,但这是一个完全没有受过教育的猜测),所以我尝试重写它:
movl -20(%ebp), %esi #gets pointer to old_string
movsbw (%edi,%esi),%dx #old_string[i] -> dx (0001)
movsbw 1(%edi,%esi),%ax #old_string[i + 1] -> ax (0002)
salw $8, %ax #shift ax left (0200)
orw %dx, %ax #or dx into ax (0201)
movw %ax,(%ecx,%ebx,2) #doesn't write to memory until end
这完全相同。
我不知道这是否是一个优化(除了一个内存写出,显然是),但如果是,我知道这不值得,并没有得到任何东西。无论如何,我得到了这段代码现在正在做的事情,感谢所有人的帮助。
答案 1 :(得分:0)
我不确定什么是不理解的,除非我遗漏了什么。
前3条指令将old_string中的一个字节加载到dx中,并将其存储到new_string中。
接下来的3条指令利用dx中已有的内容并将old_string [i + 1]与它结合起来,并将其作为16位值(ax)存储到new_string。
答案 2 :(得分:0)
此外,它将old_string [i + 1]转换为eax的高阶双字,然后 或者将edx(new_string [x])放入其中......然后将ax放入内存中!岂不 ax只包含已经在new_string [x]中的内容?所以它保存相同 在记忆中两次到同一个地方的东西?
现在你明白为什么优化者是一件好事。这种冗余代码经常出现在未经优化的生成代码中,因为生成的代码或多或少来自那些不“知道”之前或之后发生的事情的模板。