免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3202 | 回复: 11
打印 上一主题 下一主题

请教:有关堆栈的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-06-16 16:20 |只看该作者 |倒序浏览
如下程序:

== 汇编 test.asm =======================
extern abc      ; int abc(int a, int b)

[section .data]
param1 dd 1
param2 dd 2

[section .text]
global _start
global printaa

_start:
   push param2
   push param1
   call abc
   add esp, 4
   
   mov ebx, 0
   mov ebx, 1  ; sys_exit
   int 0x80      ; 系统调用

printaa:
   mov edx, [esp + 8]   ; len
   mov ecx, [esp + 4]   ; msg

   
   mov ebx, 1
   mov eax, 4   ; sys_write
   int 0x80       ; 系统调用
   ret
   

== C 程序: ltt.c ================
void printaa( char *msg, int len);

int  abc (int a, int b)
{
    if (a>b)
        printaa("a");
    else
        printaa("b");
}

对于 test.asm :
1、 _start 后面的红色语句 “add esp, 4” ,指向函数abc的第一个参数
2、printaa中蓝色部分“mov ecx, [esp + 4]”,指向函数printaa 中的第一个参数

请教各位:

那对于1和2, dword [esp + 0] 里面都有些什么?(是 eip 还是 “cs 和 ip ”)?

另:我曾在windows下debug过,但由于程序是用nasm编译的,并不能追踪到代码(感觉以前跟用masm编译、再用debug调试的不一样),不知道是否是我的调试有问题。

论坛徽章:
0
2 [报告]
发表于 2009-06-16 16:21 |只看该作者

回复 #1 sherf 的帖子

先顶一下

论坛徽章:
0
3 [报告]
发表于 2009-06-16 21:48 |只看该作者

回复 #2 sherf 的帖子

有人知道吗?

论坛徽章:
0
4 [报告]
发表于 2009-06-16 21:53 |只看该作者
你不是在C版问了吗

而已,你为何不在纸上画一画,什么都清楚了。

最主要是自己学会思考问题,动手解决问题

论坛徽章:
0
5 [报告]
发表于 2009-06-16 22:00 |只看该作者

回复 #4 mik 的帖子

mik,

我是在C版问过,但是目前还没有确定的回答......

另外,也谢谢你的建议,其实我已画过,但是还是没有答案。原因:eip和”cs+ip“都是4位,那dword [esp + 0]放的是什么?我之前认为是eip,包括目前C版里的回答都是eip,但我就是不明白为何默认是短转移(call指令只把eip压栈,而没有cs)?

论坛徽章:
0
6 [报告]
发表于 2009-06-16 22:10 |只看该作者
ret 指令需要在 [esp] 取出返回地址,因此,[esp] 必定是返回地址。

当使用 far call 和 int n 时才会压入 CS ,也就是 call  0080:08001200  这种形式才会压入 CS 。
否则都只是 near call,是不会压入 CS 的


明白什么是 far call 和 near call  没?

论坛徽章:
0
7 [报告]
发表于 2009-06-16 22:57 |只看该作者
原帖由 sherf 于 2009-6-16 22:28 发表



mik,

我的理解是call指令执行时堆栈会有变化,会压下call指令的下一条指令的IP(如果跨段会压下CS),即你所说的返回地址。你上文中提到的”也就是 call  0080:08001200  这种形式才会压入 CS“,而 ...


你真的想深入了解 x86 体系,好好的静下心来看看 amd/intel 官方的手册。

要想好好地学好每一条指令(如:call)要结合整个 x86 体系。


言归正题:

  编译器不知道 call 到底是不是 far,只有 processor 才知道 call 是 far 还是 near... ...

  现在的 OS 都是建立在 flat-segment memory 模式下(平垣模式),编译器都会将 call 编译为 near call 形式。只有在显式地写为“far call“时才是 far  call。
  so. 无论你怎么引用外部的变量,函数,都是平坦的地址偏移量。




给你一个好的忠告:
  你若真的要钻牛角下去。必须自己学会寻找答案。否则只要自寻苦恼。

论坛徽章:
0
8 [报告]
发表于 2009-06-16 23:03 |只看该作者

回复 #8 mik 的帖子

mik,

谢谢你的解答和建议。
blackoil 该用户已被删除
9 [报告]
发表于 2009-06-17 21:07 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
10 [报告]
发表于 2009-06-19 22:59 |只看该作者
同意LS几位,现在的CPU虽然支持分段机制,但是流行的OS,比如LINUX, WINDOWS根本就不用。所以很少能看到FAR CALL了。也许DOS会用FAR CALL?

PS:好像对 X86_64 的CPU,分段机制都没有了,只不过保留着那几个寄存器兼容老程序而已。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP