【发布时间】:2009-05-24 02:00:35
【问题描述】:
在编写一些 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 放入 new_string[x])
这产生了以下输出:
#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) #?
(我自己在评论,所以我可以关注正在发生的事情)。 我用 -O3 编译它,所以我也可以看到编译器如何优化某些结构。无论如何,我确信这可能很简单,但这是我不明白的:
第一部分从old_string[i] 中复制一个char,然后将它(从dx)复制到(%ecx,%ebx)。然后下一部分,复制old_string[i+1],移动它,ors 它,然后把它从ax 放到同一个地方。它将两个 16 位值放在同一个地方?这样不行吗?
此外,它会将old_string[i+1] 移动到eax 的高位双字,然后将edx (new_string[x]) 移入其中...然后将ax 放入内存! ax 不会只包含 new_string[x] 中已有的内容吗?所以它会将同样的东西保存到内存中的同一个地方两次?
我有什么遗漏吗?另外,我相当确定编译程序的其余部分与这个 sn-p 无关......我已经阅读了前后,以找到每个数组和不同变量的存储位置,以及寄存器的内容' 值将在到达该代码时出现——我认为这是对这些 C 行重要的程序集的唯一部分。
-- 哦,原来 GNU 汇编 cmets 是以 # 开头的。
【问题讨论】:
-
我很确定你的意思是 old_string 是一个 char 数组,而不是一个指向 char 的指针数组。
-
你在问为什么 -O3 没有优化更多的代码吗?
-
不,我不明白它在做什么,但我现在明白了
-
顺便说一句,你正在做这个练习真是太好了。
-
非常感谢,我真的很想成为一名软件开发人员——但我想成为那种真正知道发生了什么的人,而不是对哪些代码满足哪些要求有模糊的了解。不懂这玩意就觉得自己在撒谎,还自称是“程序员”