gpt4 book ai didi

c - 无法理解 gcc 的汇编输出

转载 作者:太空宇宙 更新时间:2023-11-04 04:09:28 24 4
gpt4 key购买 nike

在编写一些 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_stringchar数组,new_stringunsigned 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],shifting,ors,然后把它放到ax的同一个地方。它将两个 16 位值放在同一个地方?这不会行不通吗?

此外,它将 old_string[i+1] 移动到 eax 的高位双字,然后是 edx ( new_string[x]) 放入其中...然后将 ax 放入内存! ax 不会只包含 new_string[x] 中已有的内容吗?所以它会将相同的东西保存到内存中的同一个地方两次?

有什么我想念的吗?此外,我相当确定编译程序的其余部分与此代码段无关......我前后阅读过,以找到每个数组和不同变量的存储位置以及寄存器的值将在到达该代码时出现——我认为这是唯一对这些 C 行很重要的程序集。

--哦,原来 GNU 汇编注释是以 # 开头的。

最佳答案

好吧,毕竟这很简单。我用笔和纸弄明白了,写下每一步,对每个寄存器做了什么,然后给定一个初始起始值,写下每个寄存器的内容……

让我印象深刻的是它为 16 位和 8 位数据类型使用了 32 位和 16 位寄存器...这就是我认为正在发生的事情:

  • 放入内存的第一个值,比如 0001(我以为是 01)。
  • 第二个值 (02) 加载到 32 位寄存器中(就像 00000002,我在想,0002)
  • 第二个值左移 8 位(00000200,我在想,0200)
  • 第一个值(0000001,我以为是 0001)异或到第二个值(00000201,我以为是 0201)
  • 16 位寄存器放入内存(0201,我在想,又是 01)。

我不明白为什么它两次将它写入内存,或者为什么它使用 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

这完全一样。

我不知道这是否是一种优化(除了写出一个内存,这显然是),但如果是的话,我知道这并不值得,也没有给我任何好处。无论如何,我现在明白了这段代码在做什么,感谢大家的帮助。

关于c - 无法理解 gcc 的汇编输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/902896/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com