前言
文中均设i=5,汇编代码:movl $5, -4(%rbp) // 将5赋值给rdp向下偏移4个指针的头指针(i)
在装用gcc环境的PC下,可以使用gcc -S -o assembly.S yourcodefile.c
打印汇编代码。首先打印出简单自增运算的汇编代码:
i++; 的汇编代码
在早版本的编译器中可能是如下表达形式,而在最新版的gcc中,i++;
与++i;
的汇编代码是一样的。
movl -4(%rbp), %eax // 将i赋值给ax寄存器, ax=5 leal 1(%rax), %edx // 将ax寄存器的值加1赋值给dx寄存器, dx=ax+1=6 movl %edx, -4(%rbp) // 将dx寄存器的值赋值给i, i=dx=6
++i; 的汇编代码
addl $1, -4(%rbp) // 将i的值增加1赋值给i, i=6
printf函数的自增运算符
printf("%d",i++);
通过拓展i++;
的早期汇编代码,可以推出printf("$d",i++);
的汇编代码如下所示:
movl -4(%rbp), %eax // 将i赋值给ax寄存器, ax=5 leal 1(%rax), %edx // 将ax寄存器的值加1赋值给dx寄存器, dx=ax+1=6 movl %edx, -4(%rbp) // 将dx寄存器的值赋值给i, i=dx=6 movl %eax, %edx // 将ax寄存器的值赋值给dx寄存器, dx=ax=5 call _printf // 调用printf函数,打印dx寄存器的值5
不难发现,在进行自增运算操作之前,i的原始值5已经被提前存入寄存器ax中,进行完自增操作后,从ax寄存器中取出i的原始值
printf("%d",++i);
通过拓展++i;
的汇编代码,可以推出printf("$d",++i);
如下所示:
addl $1, -4(%rbp) // 将i的值增加1赋值给i, i=6 movl -4(%rbp), %eax // 将i赋值给ax寄存器, ax=6 movl %eax, %edx // 将ax寄存器的值赋值给dx寄存器, dx=ax=6 call _printf // 调用printf函数,打印dx寄存器的值6
与printf("$d",i++);
相比,主要是movl -4(%rbp), %eax
所在的位置不一致,这是由本身的性质决定的
printf("%d %d",i++,++i)
结合i++;
与++i;
的汇编代码,可以推出printf("%d%d",i++,++i)
的汇编代码如下所示:
/*++i part1 begin*/ addl $1, -4(%rbp) // 将i的值增加1赋值给i, i=6 /*++i part1 end*/ /*i++ begin*/ movl -4(%rbp), %eax // 将i赋值给ax寄存器, ax=6 leal 1(%rax), %edx // 将ax寄存器的值加1赋值给dx寄存器, dx=ax+1=7 movl %edx, -4(%rbp) // 将dx寄存器的值赋值给i, i=dx=7 /*i++ end*/ /*++i part2 begin*/ movl -4(%rbp), %edx // 将i赋值给dx寄存器, ax=7 /*++i part2 end*/ movl %edx, %ecx // 把7赋值给cx寄存器 movl %eax, %edx // 把6赋值给dx寄存器 call _printf // 调用printf函数,打印dx、cx寄存器
可见printf("%d %d",i++,++i)
的输出是6 7
printf("%d %d",i++,i++)
结合i++;
与++i;
的汇编代码,可以推出printf("%d%d",i++,++i)
的汇编代码如下所示:
/*2nd i++ begin*/ movl -4(%rbp), %edx // 将i赋值给ax寄存器, dx=5 leal 1(%rdx), %eax // 将dx寄存器的值加1赋值给ax寄存器, ax=dx+1=6 movl %eax, -4(%rbp) // 将ax寄存器的值赋值给i, i=ax=6 /*2nd i++ end*/ /*1st i++ begin*/ movl -4(%rbp), %eax // 将i赋值给ax寄存器, ax=i=6 leal 1(%rax), %ecx // 将ax寄存器的值加1赋值给cx寄存器, cx=ax+1=7 movl %ecx, -4(%rbp) // 将cx寄存器的值赋值给i, i=cx=7 /*1st i++ end*/ movl %edx, %ecx // 把5赋值给cx寄存器 movl %eax, %edx // 把6赋值给dx寄存器 call _printf // 调用printf函数,打印dx、cx寄存器
可见printf("%d %d",i++,++i)
的输出是6 5
printf("%d %d %d",i++,++i,i++)
结合i++;
与++i;
的汇编代码,可以推出printf("%d %d",i++,++i,i++)
的汇编代码如下所示:
/*2nd i++ begin*/ movl -4(%rbp), %edx // 将i赋值给ax寄存器, dx=5 leal 1(%rdx), %eax // 将dx寄存器的值加1赋值给ax寄存器, ax=dx+1=6 movl %eax, -4(%rbp) // 将ax寄存器的值赋值给i, i=ax=6 /*2nd i++ end*/ /*++i part1 begin*/ addl $1, -4(%rbp) // 将i的值增加1赋值给i, i=7 /*++i part1 end*/ /*1st i++ begin*/ movl -4(%rbp), %eax // 将i赋值给ax寄存器, ax=i=7 leal 1(%rax), %ecx // 将ax寄存器的值加1赋值给cx寄存器, cx=ax+1=8 movl %ecx, -4(%rbp) // 将cx寄存器的值赋值给i, i=cx=8 /*1st i++ end*/ /*++i part2 begin*/ movl -4(%rbp), %ecx // 将i赋值给cx寄存器, cx=8 /*++i part2 end*/ movl %edx, %n // 把5赋值给n寄存器 movl %ecx, %n2 // 把8赋值给n2寄存器 movl %eax, %edx // 把7赋值给dx寄存器 call _printf // 调用printf函数,打印dx、n2、n寄存器
可见printf("%d %d %d",i++,++i,i++)
的输出是7 8 5
,那么printf("%d %d",++i,++i)
的输出是7 7
,printf("%d %d",++i,i++)
的输出是7 5