关于函数中用一个参数修改另一个参数的一种实现方式,通过汇编可以从原理上理解分析这个问题。
先看一段示例,这里讲的是如何通过x
来修改y
#pragma warning(disable:4996)
#include<stdio.h>
int myfun(int x, int y)
{
int z = x + y;
return z;
}
int main()
{
int a = 1;
int b = 2;
int c = myfun(a, b);
printf("i am back \n");
printf("ret=%d\na=%d b=%d\n", c,a,b);
return 0;
}
运行结果
i am back
ret=3
a=1 b=2
请按任意键继续. . .
首先我们知道示例中myfun()
函数在被调用时会形成栈桢,这样就有了一个解决的方向
先观察形成过程,转到反汇编,可以看到函数调用之前的汇编
int main()
9: {
013513C0 push ebp
013513C1 mov ebp,esp
013513C3 sub esp,0E4h
013513C9 push ebx
013513CA push esi
013513CB push edi
013513CC lea edi,[ebp+FFFFFF1Ch]
013513D2 mov ecx,39h
013513D7 mov eax,0CCCCCCCCh
013513DC rep stos dword ptr es:[edi]
10: int a = 1;
013513DE mov dword ptr [ebp-8],1
11: int b = 2;
013513E5 mov dword ptr [ebp-14h],2
12: int c = myfun(a, b);
013513EC mov eax,dword ptr [ebp-14h]
013513EF push eax
013513F0 mov ecx,dword ptr [ebp-8]
013513F3 push ecx
013513F4 call 01351096
简单分析一下main
调用myfun()
之前都做了哪些工作
013513C0 push ebp
013513C1 mov ebp,esp
013513C3 sub esp,0E4h
开辟main的栈桢
10: int a = 1;
013513DE mov dword ptr [ebp-8],1
11: int b = 2;
013513E5 mov dword ptr [ebp-14h],2
初始化我们定义的 int a
,int b
;
013513EC mov eax,dword ptr [ebp-14h]
013513EF push eax
013513F0 mov ecx,dword ptr [ebp-8]
013513F3 push ecx
将初始化好的a
,b
放到栈里
013513F4 call 01351096
call
是调用的意思,也就是说myfun()
即将被调用了,call
调用时还会将一个地址放到栈里,用来作为函数将来调用结束时的返回地址(图上的01351096,其实应该是013513F9
),其他汇编在本问题中并不凸显,所以不作分析,有兴趣可以参考《微机原理》一书。
通过上面的分析,已经知道a,b所存放的地址,那么修改起来也就分容易了
此时函数myfun()的栈桢已经开辟,整数a,b都存放在栈里,如果取到a的地址,再去修改b也是可以实现的,栈的生长是向下的,b在a的下方,那么对a的地址加一就是b。
int myfun(int x, int y)
{
int *p = &x;
p++;
*p = 20;
int z = x + y;
return z;
}
运行结果
i am back
ret=21
a=1 b=2
请按任意键继续. . .