#include <STDIO.H>
int main(int argc, char* argv[])
{
int a = 0;
a = a + (a++)+(++a);
int b = 0;
b = (++b) + b + (b++);
int c = 0;
c = (c++) + c + (++c);
printf("a = %d b = %d c = %d",a,b,c);
getchar();
return 0;
}
这份代码在win7 X64系统里面 打印的结果 a= 4 b =4 c = 4
而在 其他 32位平台打印的都是 a = 2 b = 4 c = 2
记得以前有人问过我一个问题,是几个变量进行加运算然后Debug和 release版本运行起来结果不同,但是时间太久了,记不清了所以打算自己写写试试能不能找到这样的例子,但是在我的WIN 7 X64位机器上上面的例子竟然打印的全是4
而我期待的结果是 2 4 2
然后再win32和linux 32位上都是 2 4 2
鉴于这样的结果于是进入汇编层调试,看看编译器是怎么编译生成的二级制代码的
我的64位机器上的编译的结果如下
三种顺序加法都是一样的先计算++a 然后 计算三个数相加 然后计算 a++
编译器相同的但是就是因为一个电脑是64位的一个是32位的就出现不同的结果
在汇编级别进行调试发现了问题
32位 的反汇编
.text:00401028 mov [ebp+var_4], 0 ; a = 0
.text:0040102F mov eax, [ebp+var_4] ; 取出a 然后计算 a+(a++)
.text:00401032 add eax, [ebp+var_4] ; a+(a++) 也就是 a+a
.text:00401035 mov ecx, [ebp+var_4] ; 此时写回 a的值为0
.text:00401038 add ecx, 1 ; 在进行+(++a)操作之前先进行 ++a操作
.text:0040103B mov [ebp+var_4], ecx ; 此时写回 a的值为1
.text:0040103E add eax, [ebp+var_4] ; 把++a之后的a值和 a+(a++)进行加 0+1
.text:00401041 mov [ebp+var_4], eax ; 此时写回 a的值为1
.text:00401044 mov edx, [ebp+var_4]
.text:00401047 add edx, 1 ; 最后进行a++操作 1++ =2
.text:0040104A mov [ebp+var_4], edx
.text:0040104D mov [ebp+var_8], 0 ; b = 0
.text:00401054 mov eax, [ebp+var_8] ; 计算 ++b
.text:00401057 add eax, 1
.text:0040105A mov [ebp+var_8], eax ; b =1
.text:0040105D mov ecx, [ebp+var_8]
.text:00401060 add ecx, [ebp+var_8] ; (++b)+b 1+1 = 2
.text:00401063 add ecx, [ebp+var_8] ; {(++b)+b}+(b++) {2}+1=3 也就是之前的结果再加上一个b
.text:00401066 mov [ebp+var_8], ecx ; 因为b++ 是先使用再进行++操作
.text:00401069 mov edx, [ebp+var_8]
.text:0040106C add edx, 1 ; 最后计算b++ 3+1 =4
.text:0040106F mov [ebp+var_8], edx
.text:00401072 mov [ebp+var_C], 0 ; c = 0
.text:00401079 mov eax, [ebp+var_C]
.text:0040107C add eax, [ebp+var_C] ; (c++)+c 0+0 =0
.text:0040107F mov ecx, [ebp+var_C] ; 计算 ++c
.text:00401082 add ecx, 1
.text:00401085 mov [ebp+var_C], ecx ; ++c 计算之后 c的值为1
.text:00401088 add eax, [ebp+var_C] ; 计算 {(c++)+c}+(++c)也就是0+1 =1
.text:0040108B mov [ebp+var_C], eax
.text:0040108E mov edx, [ebp+var_C] ; 最后计算 c++ c=2
.text:00401091 add edx, 1
.text:00401094 mov [ebp+var_C], edx
.text:00401097 mov eax, [ebp+var_C]
.text:0040109A push eax
.text:0040109B mov ecx, [ebp+var_8]
.text:0040109E push ecx
.text:0040109F mov edx, [ebp+var_4]
.text:004010A2 push edx
.text:004010A3 push offset Format ; "a = %d b = %d c = %d"
.text:004010A8 call _printf
我的64位 编译生成的结果却并不同
.text:0040102E mov [ebp+a], 0
.text:00401035 mov eax, [ebp+a]
.text:00401038 add eax, 1
.text:0040103B mov [ebp+a], eax
.text:0040103E mov ecx, [ebp+a]
.text:00401041 add ecx, [ebp+a]
.text:00401044 add ecx, [ebp+a]
.text:00401047 mov [ebp+a], ecx
.text:0040104A mov edx, [ebp+a]
.text:0040104D add edx, 1
.text:00401050 mov [ebp+a], edx
.text:00401053 mov [ebp+b], 0
.text:0040105A mov eax, [ebp+b]
.text:0040105D add eax, 1
.text:00401060 mov [ebp+b], eax
.text:00401063 mov ecx, [ebp+b]
.text:00401066 add ecx, [ebp+b]
.text:00401069 add ecx, [ebp+b]
.text:0040106C mov [ebp+b], ecx
.text:0040106F mov edx, [ebp+b]
.text:00401072 add edx, 1
.text:00401075 mov [ebp+b], edx
.text:00401078 mov [ebp+c], 0
.text:0040107F mov eax, [ebp+c]
.text:00401082 add eax, 1
.text:00401085 mov [ebp+c], eax
.text:00401088 mov ecx, [ebp+c]
.text:0040108B add ecx, [ebp+c]
.text:0040108E add ecx, [ebp+c]
.text:00401091 mov [ebp+c], ecx
.text:00401094 mov edx, [ebp+c]
.text:00401097 add edx, 1
.text:0040109A mov [ebp+c], edx
.text:0040109D mov eax, [ebp+c]
.text:004010A0 push eax
.text:004010A1 mov ecx, [ebp+b]
.text:004010A4 push ecx
.text:004010A5 mov edx, [ebp+a]
.text:004010A8 push edx
.text:004010A9 push offset format ; "a = %d b = %d c = %d"
.text:004010AE call _printf
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)