zoukankan      html  css  js  c++  java
  • 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 7printf("%d %d",++i,i++)的输出是7 5

  • 相关阅读:
    layui 相关知识
    ideal debug 启动不起来
    删除命令 rm -rf maven-project-jxcg.zip 解压 unzip maven-project-jxcg.zip
    vsb 配置
    cmd dos
    switch
    Element UI 框架搭建
    mysql 远程连接设置
    YApi可视化接口管理平台 接口
    报403错误
  • 原文地址:https://www.cnblogs.com/shy-/p/11874621.html
Copyright © 2011-2022 走看看