学习日志:call_test.c程序分析

1.完整代码

#include <stdio.h>
#include <stdlib.h>
int incr(int *p, int val) {
    int x = *p;
    int y = x + val;
    *p = y;	
    return x;
}

int call_incr2(int x) {
    int v1 = 15213;
    int v2 = incr(&v1, 3000);
	printf("v1= %d\n &v1= %p\n v2= %d\n &v2= %p\n", v1,&v1,v2,&v2);
	printf("x= %d\n &x= %p\n", x,&x);
    return x+v2;
}

int call_incr() {
    int v1 = 15213;
    int v2 = incr(&v1, 3000);
	printf("v1= %d\n &v1= %p\n v2= %d\n &v2= %p\n", v1,&v1,v2,&v2);	
    return v1+v2;
}

int main(int argc, char *argv[]) {
    if (argc > 1){
	int n=atoi(argv[1]);
	if (n==1)
	{
		int v = call_incr();
		printf("v1+v2 = %d\n", v);	
	}
	else if (n==2)
	{
		int v = call_incr2(1000);	
		printf("x+v2= %d\n",v);
	}}
	
	return 0;
}

2.代码分析

(1)主函数中“int main(int argc,char *argv[])”,

“形参argc是整型变量,用于存放命令行中参数的个数,因为程序名也计算在内,所以argc的值至少为1。形参argv是字符指针数组,数组中的每一个元素都是一个字符串指针,指向命令行中的一个命令行参数。”

(2)第27行“atoi()”,(在标准库<stdlib.h>中)

“C 库函数 int atoi(const char *str) 把参数 str 所指向的字符串转换为一个整数(类型为 int 型)。”

(3)主函数的选择语句,表示当命令行中输入参数“1”时,调用函数“call_incr()”,当命令行中输入参数“2”时,调用函数“call_incr2()”。

(4)函数“call_incr()”与“call_incr2()”的区别仅仅是最后返回的数据不相同,然后“call_incr2()”有参数传递,而“call_incr()”没有。

(5)在“incr()”函数中,形参“*p”指向的是“v1”的地址,val = 3000。“int x = *p”将指针“p”指向的值赋给了“x”,即将“v1”的值赋给了“x”。“int y = x + val”,即y = v1+val,然后“*p = y”,将“p”指向的数赋值为“y”,即此时v1的值变为v1+val。

3.运行程序并分析结果

(1)在命令行中输入“gcc -o call_test.o call_test.c”,“./call_test.o 1”。结果如图:
在这里插入图片描述
分析:此时调用了函数“call_incr()”,根据开始的代码分析,在该函数调用“incr()”之后,v1 = v1+val = 15213+3000 = 18213,v2 = x = *p = 15213。所以,最后有v1+v2 = 18213+15213 = 33426。我们还发现v1的地址和V2的地址正好相差4个字节,即为整型所占的字节数。

(2)在命令行中再输入“./call_test.o 2”。结果如图:
在这里插入图片描述
分析:前一部分的分析和“call_incr()”的相同,只是最后返回的数据为x+v2 = 1000+15213=16213。同样可以发现x,v1,v2的地址依次相差4个字节,即为整形所占字节数。

3.反编译结果

结果:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

incr()分析:

①前两句,先将基指针入栈,然后将基指针指到栈指针的位置。

②形参整形指针p按规定存储在寄存器“%rdi”中,“mov %rdi,-0x18(%rbp)”,将形参p入栈,位置在“-0x18(%rbp)”

③形参整形val存储在寄存器“%esi”中,“mov %esi,-0x1c(%rbp)”,将形参val入栈,位置在“-0x1c(%rbp)”

④“mov -0x18(%rbp),%rax”即将p所指向的地址存储在寄存器“%rax”中

⑤“mov (%rax),%eax”即将“%rax”中存储的地址所存的数据存储在“%eax”中,(4)和(5)两句代表着C语言中的“int x = *p;”

⑥“mov %eax,-0x8(%rbp)”,将寄存器“%eax”中的值存储在“-0x8(%rbp)”中,即将x的值存储在“-0x8(%rbp)”中

⑦“mov -0x8(%rbp),%edx”,将x的值存储在寄存器“%edx”当中

⑧“-0x1c(%rbp),%eax”,“-0x1c(%rbp)”之前存放的值是val,指一句就是将val的值存储在寄存器“%eax”当中

⑨“add %edx,%eax”,即%eax = %eax + %edx,即将x+val的值存储在寄存器“%eax”当中

⑩“mov %eax,%-0x4(%rbp)”,将%eax存储器中的数据入栈,存储在“%-0x4(%rbp)”

⑪“mov -0x18(%rbp),%rax”,之前“-0x18(%rbp)”中存储的是p指向的地址的值,这一句即将p指向的地址(即x的地址)存储在寄存器%rax当中

⑫“mov -0x4(%rbp),%edx”,%-0x4(%rbp)中存储的值为x+val,这一句将x+val的值存储在寄存器%edx当中,此时完成C语言当中的语句“int y=x+val;”

⑬“mov %edx,(%rax)”,此句将%edx中存储的值赋值给在%rax存储的地址所指向的数据,对应于C语言中的“*p = y;”

⑭“mov -0x8(%rbp),%eax”,就是将x的值存储在寄存器%eax中

⑮最后退栈并返回寄存器%eax当中的值,即返回x

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值