在汇编级别了解++ i和i ++之间的区别 [英] Understanding the difference between ++i and i++ at the Assembly Level

查看:78
本文介绍了在汇编级别了解++ i和i ++之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这里曾多次问过这个问题,但我没有问这两者之间有什么区别.只是希望对理解这两种形式背后的装配有所帮助.

I know that variations of this question has been asked here multiple times, but I'm not asking what is the difference between the two. Just would like some help understanding the assembly behind both forms.

我认为我的问题与差异的原因关系更大.

I think my question is more related to the whys than to the what of the difference.

我正在阅读 Prata的C Primer Plus ,在处理增量运算符 ++ 的部分以及使用 i ++ ++ i 作者说,如果运算符是自己使用的,例如 ego ++; ,那么我们使用哪种形式都没关系.

I'm reading Prata's C Primer Plus and in the part dealing with the increment operator ++ and the difference between using i++ or ++i the author says that if the operator is used by itself, such as ego++; it doesn't matter which form we use.

如果我们仔细看下面的代码(与Xcode一起编译,Apple LLVM版本9.0.0(clang-900.0.39.2)):

If we look at the dissasembly of the following code (compiled with Xcode, Apple LLVM version 9.0.0 (clang-900.0.39.2)):

int main(void)
{
    int a = 1, b = 1;

    a++;
    ++b;

    return 0;

}

我们可以看到使用的形式确实无关紧要,因为两者的汇编代码是相同的(两个变量都将在屏幕上显示2).

we can see that indeed the form used doesn't matter, since the assembly code is the same for both (both variables would print out a 2 to the screen).

a b 的初始化:

0x100000f8d <+13>: movl   $0x1, -0x8(%rbp)
0x100000f94 <+20>: movl   $0x1, -0xc(%rbp)

a ++ 的程序集:

0x100000f9b <+27>: movl   -0x8(%rbp), %ecx
0x100000f9e <+30>: addl   $0x1, %ecx
0x100000fa1 <+33>: movl   %ecx, -0x8(%rbp)

++ b 的程序集:

0x100000fa4 <+36>: movl   -0xc(%rbp), %ecx 
0x100000fa7 <+39>: addl   $0x1, %ecx 
0x100000faa <+42>: movl   %ecx, -0xc(%rbp)


然后作者声明,当运算符及其操作数是较大表达式的一部分时,例如,在赋值语句中,使用前缀或后缀确实会有所不同.


Then the author states that when the operator and its operand are part of a larger expression as, for example, in an assignment statement the use of prefix or postfix it does make a difference.

例如:

int main(void)
{
    int a = 1, b = 1;
    int c, d;

    c = a++;
    d = ++b;

    return 0;

}

这将分别为 c b 打印 1 2 .

并且:

a b 的初始化:

0x100000f46 <+22>: movl   $0x1, -0x8(%rbp)
0x100000f4d <+29>: movl   $0x1, -0xc(%rbp)

c = a ++; 的组装:

0x100000f54 <+36>: movl   -0x8(%rbp), %eax      // eax = a = 1
0x100000f57 <+39>: movl   %eax, %ecx            // ecx = 1
0x100000f59 <+41>: addl   $0x1, %ecx            // ecx = 2
0x100000f5c <+44>: movl   %ecx, -0x8(%rbp)      // a = 2
0x100000f5f <+47>: movl   %eax, -0x10(%rbp)     // c = eax = 1

d = ++ b; 的组装:

0x100000f62 <+50>: movl   -0xc(%rbp), %eax      // eax = b = 1
0x100000f65 <+53>: addl   $0x1, %eax            // eax = 2
0x100000f68 <+56>: movl   %eax, -0xc(%rbp)      // b = eax = 2
0x100000f6b <+59>: movl   %eax, -0x14(%rbp)     // d = eax = 2

很明显,分配的汇编代码不同:

Clearly the assembly code is different for the assignments:

  • c = a ++; 的形式包括使用寄存器 eax ecx .它使用 ecx 执行 a 乘以 1 的增量,但是使用 eax 进行赋值.

  • The form c = a++; includes the use of the registers eax and ecx. It uses ecx for performing the increment of a by 1, but uses eax for the assignment.

形式 d = ++ b; 使用 ecx 来使 b 递增 1

The form d = ++b; uses ecx for both the increment of b by 1 and the assignment.

我的问题是:

  • 那是为什么?
  • 是什么决定 c = a ++; 需要两个寄存器而不是一个(例如, ecx )?
  • Why is that?
  • What determines that c = a++; requires two registers instead of just one (ecx for example)?

推荐答案

一个好的编译器会将整个代码替换为 c = 1;d = 2; .而且,如果不依次使用这些变量,则整个程序就是一个很大的 NOP -根本就不会生成任何机器代码.

A good compiler would replace this whole code with c = 1; d = 2;. And if those variables aren't used in turn, the whole program is one big NOP - there should be no machine code generated at all.

但是您要做会获得机器代码,因此您无法正确启用优化器.讨论未优化的C代码的效率是毫无意义的.

But you do get machine code, so you are not enabling the optimizer correctly. Discussing the efficiency of non-optimized C code is quite pointless.

如果提到特定的编译器,则讨论特定的编译器未能优化代码可能是有意义的.这里不是这种情况.

Discussing a particular compiler's failure to optimize the code might be meaningful, if a specific compiler is mentioned. Which isn't the case here.

所有这些代码表明,您的编译器做得不好,可能是因为您没有启用优化,仅此而已.无法得出其他结论.特别是,关于 i ++ ++ i 的行为的有意义的讨论是不可能的.

All this code shows is that your compiler isn't doing a good job, possibly because you didn't enable optimizations, and that's it. No other conclusions can be made. In particular, no meaningful discussion about the behavior of i++ versus ++i is possible.

这篇关于在汇编级别了解++ i和i ++之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆