printf中的自增运算符
Posted shy-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了printf中的自增运算符相关的知识,希望对你有一定的参考价值。
前言
文中均设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
以上是关于printf中的自增运算符的主要内容,如果未能解决你的问题,请参考以下文章