天书夜读 中的一个例子,没有看明白,还请牛人可以帮忙解答下,谢谢

wenhui45 2009-02-22 02:31:03
函数和堆栈的关系密切,这是因为:我们通过堆栈把参数从外部传入到内部。此外,我们在堆栈中划分区域来容纳函数的内部变量。
调用push 和pop 指令的时候,寄存器esp 用于指向栈顶的位置。栈顶总是栈中地址最小的位置。push 执行的结果,esp 总是减少。
pop 则增加。
C 语言所写的程序中,堆栈用于传递函数参数。这时称为调用栈。
写一个简单的函数如下:
void myfunction(int a,int b)
{
int c = a+b;
}
这是标准的C 函数调用方式.其过程是:
1) 调用方把参数反序的压入堆栈中。
2) 调用函数。
3) 调用方把堆栈复原。
而被调用函数需要做以下一些事情:
1) 保存ebp. ebp 总是被我们用来保存这个函数执行之前的esp 的值。执行完毕之后,我们用ebp 恢复esp.同时,调用我们的上
层函数也用ebp 做同样的事情。所以我们之前先把ebp 压入堆栈。返回之前弹出,避免ebp 被我们改动。
2) 保存esp 到ebp 中。
上面两步的代码如下:
push ebp ;保存ebp,并把esp 放入ebp 中
;此时ebp 与esp 同。
mov ebp,esp ;都是这次函数调用时的栈顶。
3) 在堆栈中腾出一个区域用来保存局部变量。这就是常说的所谓局部变量在栈空间中。方法为把esp 减少一个数值。这样等于压
入了一堆变量。日后要恢复时,只要把esp 恢复成ebp 中保存的数据就可以了.
4) 保存ebx,esi,edi 到堆栈中。函数调用完后恢复。这是一个编程规范。
对应的代码如下:
sub esp,0cch ;把esp 往上移动一个范围,等于在堆栈中放出一片新
;的空间用来存局部变量.
push ebx ;下面保存三个寄存器:ebx,esi,edi,这也是C 规范.
push esi
push edi
5) 把局部变量区域初始化成0cccccccch。0cccccccch 实际是INT 3.这是一个中断指令。因为局部变量不可能被执行,如果执行
了必然程序有错,这时发生中断来提示开发者。这是VC 编译DEBUG 版本的特有操作。
相关代码如下:
lea edi,[ebp-0cch] ;本来是要mov edi,ebp-0cch,但是mov 不支持-操作。所
;以对ebp-0cch 取内容,而lea 把内容的地址也就是ebp
;-0cch加载到edi 中.目的是把保存局部变量的区域(从
;ebp-0cch开始的区域)初始化成全部0cccccccch.
mov ecx,33h
mov eax,0cccccccch
rep stos dword ptr [edi] ;拷贝字符串
6) 然后做函数里应该做的事情。参数的获取是ebp+8 字节为第一个参数,ebp+12 为第二个参数,依次增加。ebp+4 字节处是
要返回的地址。
7) 恢复ebx,esi,edi ,esp,ebp,最后返回。
代码如下:
pop edi ;恢复edi,esi,ebx
pop esi
pop ebx
mov esp,ebp ;恢复原来的ebp 和esp,让上一个调用的函数正常使用.
pop ebp
ret




上面是书中的分析:疑问如下

在第2)步中,ebp被赋予了esp的值,这时ebp等于esp,那第6)步为什么又说ebp+8 字节为第一个参数,ebp+12 为第二个参数,ebp+4 字节处是
要返回的地址。
此时ebp+8,ebp+12怎么会是参数的地址呢?我觉得应该是ebp-8和ebp-12才对啊,(因为第3)步说:把esp 减少一个数值。这样等于压
入了一堆变)


还有一个就是第5)步中mov ecx,33h这一句,这一句应该是控制循环的次数的,但是又为什么这个循环的次数是33h呢?没明白!!

...全文
142 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
yongmen 2009-02-23
  • 打赏
  • 举报
回复
lea edi,[ebp-0cch]这一句一共cch个字节,也就是要cch除以4个0cccccccch,供33h个0cccccccch,应该是这样吧!
wenhui45 2009-02-22
  • 打赏
  • 举报
回复
8楼的哥们,我想问下,那个分配局部变量的物理次数是根据什么来定的啊(下面这段)

5) 把局部变量区域初始化成0cccccccch。0cccccccch 实际是INT 3.这是一个中断指令。因为局部变量不可能被执行,如果执行
了必然程序有错,这时发生中断来提示开发者。这是VC 编译DEBUG 版本的特有操作。
相关代码如下:
lea edi,[ebp-0cch] ;本来是要mov edi,ebp-0cch,但是mov 不支持-操作。所
;以对ebp-0cch 取内容,而lea 把内容的地址也就是ebp
;-0cch加载到edi 中.目的是把保存局部变量的区域(从
;ebp-0cch开始的区域)初始化成全部0cccccccch.
mov ecx,33h
mov eax,0cccccccch
rep stos dword ptr [edi] ;拷贝字符串




mov ecx,33h ecx是用来控制循环次数,但是为什么是33h,而不是其他呢?明天我多给你点分,今天改不了了

你上面那个说的我已经明白了,就剩这个了
wenhui45 2009-02-22
  • 打赏
  • 举报
回复
不好意思啊,我刚注册的,分不多,以后会多给的
kilrogg 2009-02-22
  • 打赏
  • 举报
回复
ps:lz好抠门啊,2分的帖,>_<
kilrogg 2009-02-22
  • 打赏
  • 举报
回复
先弄清进函数时,栈的结构,以及参数和局部变量的区别(ebp-8这个就是局部变量,而不是参数)
进栈前时:
...
@-0Ch
@-8
@-4
@+0 ====>esp,参数1 进函数前,压的参数
@+4 ===> 参数2
@+8
...
进栈,再push ebp;mov ebp,esp后
...
@-0Ch ===>局部变量1
@-8 ====>保存的ebp,此时的esp基数--ebp
@-4 ====>返回地址
@+0 ====> 参数1
@+4====> 参数2
@+8
...
依次类推


wenhui45 2009-02-22
  • 打赏
  • 举报
回复
二楼的意思是:参数是在返回地址入栈之前压入堆栈的吗?可是上面那一段代码好像不是这么写的,那个是一个C的反汇编程序
wenhui45 2009-02-22
  • 打赏
  • 举报
回复
是的没错,是循环的次数,我所不明白的是为什么是这么多次循环?为什么是33h , 而不是其他
wenhui45 2009-02-22
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 schlafenhamster 的回复:]
ebp常用于保存堆栈frame,一旦mov ebp, esp后用ebp来存取参数比用esp方便.push ebp 时使esp又小了4,所以第一个参数在 ebp+8处(其中原ebp+4,返回地址+4)...
[/Quote]

每次入栈后,地址是变小的,push ebp 时使esp又小了4,也就是esp-4,这时候又把参数入栈,那参数的地址不就应该是ebp-8处了吗?怎么会是ebp+8呢?
NaiNaiGeXiong 2009-02-22
  • 打赏
  • 举报
回复
我没有你说的什么“天书夜读”,所以不知道你说的例子是要完成什么样的功能,所以就不知道你的第二个问题的答案,第5)步有:
rep stos dword ptr [edi] ;拷贝字符串
那循环的次数我想就是要往内存中存入多少个dword的信息
NaiNaiGeXiong 2009-02-22
  • 打赏
  • 举报
回复
输入错了最后一句:
“完成上面两句后,esp+0指向ebp旧值,esp+4指向的就是反回地址,esp+8就是第一个参数了。”
改为:完成上面两句后,ebp+0指向ebp旧值,ebp+4指向的就是反回地址,ebp+8就是第一个参数了。
其实ebp就等于esp!!!
NaiNaiGeXiong 2009-02-22
  • 打赏
  • 举报
回复
因为所谓的堆栈是从高地址向地址生长的,进栈的操作即分两步:
1、esp-4 ;
2、把要进栈的值放入[esp-4]处;

在你的疑问中:
push 第二个参数 ;同下
push 第一个参数 ;参数的入栈顺序是从右到左的,即esp=esp-4,并把参数入栈
push 反回地址 ;就是esp=esp-4,并把反回地址压入堆栈
push ebp ;就是esp=esp-4,并把ebp的值压入堆栈
mov ebp, esp ;此时esp指向旧的ebp值
完成上面两句后,esp+0指向ebp旧值,esp+4指向的就是反回地址,esp+8就是第一个参数了。
schlafenhamster 2009-02-22
  • 打赏
  • 举报
回复
ebp常用于保存堆栈frame,一旦mov ebp, esp后用ebp来存取参数比用esp方便.push ebp 时使esp又小了4,所以第一个参数在 ebp+8处(其中原ebp+4,返回地址+4)...

21,458

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧