首页
论坛
课程
招聘
[旧帖] 实参入栈过程[求助] 0.00雪花
2010-4-30 17:44 1050

[旧帖] 实参入栈过程[求助] 0.00雪花

2010-4-30 17:44
1050
C++调用汇编中的一个过程,并传递三个参数
c++中声明如下:
extern "C" int __stdcall test(char *p,  char *q, char *r);
....
addr=test(p,q,r); //p, q, r 是三个数组名
printf("addr=%08x, p=%08x, q=%08x, r=%08x\n", addr, p ,q, r);

汇编部分代码:
   ...
   PUSH EBP
    MOV EBP ,ESP
    MOV EAX, [EBP+12]   ;EAX值应该是q,但结果是p
    ....
    POP EBP

编译执行后,C++中addr的值与p的值相同
我也测试了下其他的偏移地址
[EBP+12]   =   p
[EBP+16]   =   q
[EBP+20]   =   r

这是怎么回事啊?
首先说下我的理解, c++ 中调用test时,先push r, push q, push p, 然后再push返回的指令地址(应该是EIP吧,4个字节),进入汇编test过程后,先push ebp进行保存,然后ebp指向原先的ebp内容。我期待的结果是:  p=[ebp+8], q=[ebp+12], r=[ebp+16]

希望大家解决我的疑问.谢谢。

[2022冬季班]《安卓高级研修班(网课)》月薪三万班招生中~

收藏
点赞0
打赏
分享
最新回复 (6)
雪    币: 128
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
joeyye 活跃值 2010-4-30 17:51
2
0
__cdecl 是你理解那种, __stdcall 恰好相反, 就是你看到的pqr这个入栈顺序
雪    币: 70
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
younghust 活跃值 2010-4-30 18:00
3
0
不对吧,我在网上查了下。__stdcall 和__cdecl都是采用自右向左的入栈方式,也就是push r , push q , push p

那[EBP+12]等于p又怎么解释呢,不是应该是[EBP+8]吗?
雪    币: 100
活跃值: 活跃值 (23)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
hearmecryle 活跃值 1 2010-4-30 18:29
4
0
我认为:
EBP+4=ret
EBP+8=参数1
EBP+C=参数2
EBP+10=参数3
......
StdCall
雪    币: 70
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
younghust 活跃值 2010-4-30 20:48
5
0
嗯。我原先的预期结果也是这样的。可结果不是这样的,
EBP+0c=参数1
EBP+10=参数2
EBP+14=参数3
雪    币: 360
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
rol 活跃值 2010-4-30 20:50
6
0
你调试一下,看看ebp+8是什么不就行了吗,说不准是个隐含指针呢,不看不知道
雪    币: 70
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
younghust 活跃值 2010-5-1 21:46
7
0
今天我又看了会。知道为什么了。
因为汇编子过程里,开始的时候,我手动写了
PUSH EBP
MOV EBP, ESP
VC在编译时,会自动产生的。这样就相当于EBP进了两次栈。所以后面第一个参数是 [EBP+12]。我把自己添加的前面两行去掉后,就可以了。[EBP+4]是返回地址,[EBP+8]是第一个参数,,[EBP+12]是第二个参数,[EBP+16]是第三个参数。

谢谢大家的帮助!
游客
登录 | 注册 方可回帖
返回