CS:APP第3章汇编疑问:x+=y;(*p)+=5为何被编译为y+=x+5?
问题解答
1. 你重写的C代码运行结果错误的原因
你重写的代码仅将增量合并到y的计算中,没有同步更新变量x的值,和原C代码的逻辑完全不符:
原C代码循环体中x += y和(*p) +=5会修改x的取值,下一轮循环的计算会使用更新后的x值;而你的代码里x始终是初始传入的值,每轮循环的增量固定为初始x+5,自然会得到错误结果。
2. 编译器将两条C语句合并为y +=x +5操作的原理
- 首先编译器做了别名分析:通过静态分析确认指针p始终指向x,没有其他修改路径,因此
(*p) +=5完全等价于x +=5,不需要额外的访存操作。 - 其次编译器做了算术优化:原循环体中与x、y相关的操作序列为:
x += y→ 计算得到新x值:x_new = x_old + y_oldx +=5→ x更新为:x_new = x_old + y_old +5y +=x→ y更新为:y_new = y_old + x_new
编译器在保证语义等价的前提下,利用leaq指令的地址计算特性(不需要访存,直接完成基址+变址+偏移的算术计算),将多个算术操作合并,leaq 5(%rbx,%rcx),%rcx就是直接完成rcx = rbx + rcx +5的计算,对应合并后的y增量操作,同时编译器会单独保存更新后的x值供下一轮循环使用,不会丢失x的更新语义。
正确的C代码参考
short dw_loop (short x) { short y = x / 9; short *p = &x; short n = 4 * x; do { x += y; *p +=5; y +=x; n -= 2; } while (n > 0); return y; };
内容的提问来源于stack exchange,提问作者Ray
相关产品推荐
相关产品推荐

