| 2009年5月26日
前几天和王老师在调式一个程序,调试结果怎么都不正确。其实形式很简单: printf("%d; %d", sum(), m); m是一个静态变量,在sum中改变,但是打印结果还是没有变化。 当然在后来我又作了一个测试发现在gcc编译的程序中他是以左优先的,也就是先打印计算m的结果,让后在计算sum的结果,再打印。
昨天在使用汇编分析程序的时候才发现真是这样的,在汇编程序中参数一般使用寄存器或是堆栈来传递,在gcc的编译中使用这几乎同时使用了这两种方式。例如下面这段程序
#include <stdio.h>
int main(int args, char *argv[])
{
printf("num: %d num: %d \n", 5, 6);//这里printf使用了三个参数
return 0;
}
其汇编程序如下的:(使用:”gcc -S hello.c“ 生成其相应的汇编程序)
.file "hello.c"
.section .rodata
.LC0:
.string "num: %d num: %d \n"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $20, %esp
movl $6, 8(%esp) //这里处理第三个参数
movl $5, 4(%esp) //这里是第二个参数
movl $.LC0, (%esp) //这里是第一个参数
call printf //这里调用printf函数
movl $0, %eax
addl $20, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (Debian 4.3.2-1.1) 4.3.2"
.section .note.GNU-stack,"",@progbits
根据上面的代码可以清楚的看到参数处理顺序的先后,从而导致了执行结果的先后。 下面在来一个简单的例子:
#include <stdio.h>
int main(int args, char *argv[])
{
int i = 10;
printf("i: %d i+: %d \n", i++, i++);//这里printf使用了三个参数
return 0;
}
其汇编程序如下的:(使用:”gcc -S hello.c“ 生成其相应的汇编程序)
.file "hello.c"
.section .rodata
.LC0:
.string "i: %d i+: %d \n"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp //将堆栈指针放到ebp中
pushl %ecx //这里是保存堆栈指针
subl $36, %esp //
movl $10, -8(%ebp) //
movl -8(%ebp), %edx //这两句是把10放到edx中
addl $1, -8(%ebp)
movl -8(%ebp), %eax //这两句是把i++放到eax中
addl $1, -8(%ebp) //这里再次把i加1
movl %edx, 8(%esp) //这里是第三个参数 这里的结果是10
movl %eax, 4(%esp) //这里是第二个参数 这里的结果是11
movl $.LC0, (%esp) //这里是第一个参数 这里的结果是"i: %d i+: %d \n"
call printf //调用printf
movl $0, %eax //返回值放到eax中
addl $36, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (Debian 4.3.2-1.1) 4.3.2"
.section .note.GNU-stack,"",@progbits
argc.s 1,2-9 All
"argc.s" 33L, 576C
关注「黑光技术」,关注大数据+微服务