printf中的自增运算符

非 Y 不嫁゛ 提交于 2019-12-04 16:40:52

前言

文中均设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 7printf("%d %d",++i,i++)的输出是7 5

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!