繁体   English   中英

装配与C代码比较

[英]Assembly Compared With C code

我目前正在学习汇编和C编程语言,我有几个问题。

C代码

int arith(int x, int y, int z) {
    int t1 = x + y;
    int t2 = z*48;
    int t3 = t1 & 0xFFFF;
    int t4 = t2 * t3;
    return t4;
}

汇编代码

movl  16(%ebp),%eax         z
leal  (%eax,%eax,2), %eax   z*3
sall  $4,%eax               t2 = z*48
movl  12(%ebp),%edx         y
addl  8(%ebp),%edx          t1 = x+y
andl  $65535,%edx           t3 = t1&0xFFFF
imull %edx,%eax             Return t4 = t2*t3

而不是使用leal然后移动4乘以z乘以48,我可以使用imull $ 48,%eax吗?

此外,这是多次使用%edx寄存器。 这是否意味着t1被覆盖? 换句话说,如果我想,我还能在t4之前检索t1吗?

尝试将程序集与代码逐行匹配可能不是解决此问题的最佳方法。 编译器进行了一些优化以使程序尽可能高效地运行,这就是为什么您可能会注意到代码之间存在一些不一致的原因。

要回答你的第一个问题,从技术上来说可行,但编译器再次做了几次优化。 因此,虽然使用imul看起来更直观,但编译器确定leal和sall更有效。 编辑:我只是想指出,在可能的情况下,几乎总是使用位移运算符而不是imul。 CPU的位移更便宜,因为它实际上只是改变位值而不是尝试执行可能需要更多CPU时间的数学运算。

现在关于“覆盖”t1。 程序集没有任何关于程序变量的信息 - 它只知道它需要对某些值执行某些操作。 虽然程序集可能使用4个不同的寄存器来存储t1-4,但编译器确定它是不必要的,并且您只需要2个寄存器来存储所有值。 如果你考虑一下,这应该是有道理的。 您的功能可以简化为几行代码。 显然,这不是一个好主意,因为这会使其无法阅读,但装配不一定是“可读的”。 如果你回到你的程序并在返回t4之前用t1执行了一些其他操作,你可能会注意到你的程序集与以前不同,并且它可能正在使用另一个寄存器,具体取决于值的使用方式。

如果您真的想在程序集中使用程序的准系统版本,请使用-Og标志进行编译以关闭编译器优化。 它可能仍然不完全匹配您的代码,但它可能使您更容易理解正在发生的事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM