请教:有关堆栈的问题
如下程序:== 汇编 test.asm =======================
extern abc ; int abc(int a, int b)
param1 dd 1
param2 dd 2
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, ; len
mov ecx, ; msg
mov ebx, 1
mov eax, 4 ; sys_write
int 0x80 ; 系统调用
ret
== C 程序: ltt.c ================
void printaa( char *msg, int len);
intabc (int a, int b)
{
if (a>b)
printaa("a");
else
printaa("b");
}
对于 test.asm :
1、 _start 后面的红色语句 “add esp, 4” ,指向函数abc的第一个参数
2、printaa中蓝色部分“mov ecx, ”,指向函数printaa 中的第一个参数
请教各位:
那对于1和2, dword 里面都有些什么?(是 eip 还是 “cs 和 ip ”)?
另:我曾在windows下debug过,但由于程序是用nasm编译的,并不能追踪到代码(感觉以前跟用masm编译、再用debug调试的不一样),不知道是否是我的调试有问题。
回复 #1 sherf 的帖子
先顶一下回复 #2 sherf 的帖子
有人知道吗? 你不是在C版问了吗而已,你为何不在纸上画一画,什么都清楚了。
最主要是自己学会思考问题,动手解决问题
回复 #4 mik 的帖子
mik,我是在C版问过,但是目前还没有确定的回答......
另外,也谢谢你的建议,其实我已画过,但是还是没有答案。原因:eip和”cs+ip“都是4位,那dword 放的是什么?我之前认为是eip,包括目前C版里的回答都是eip,但我就是不明白为何默认是短转移(call指令只把eip压栈,而没有cs)? ret 指令需要在 取出返回地址,因此, 必定是返回地址。
当使用 far call 和 int n 时才会压入 CS ,也就是 call0080:08001200这种形式才会压入 CS 。
否则都只是 near call,是不会压入 CS 的
明白什么是 far call 和 near call 没? 原帖由 sherf 于 2009-6-16 22:28 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
mik,
我的理解是call指令执行时堆栈会有变化,会压下call指令的下一条指令的IP(如果跨段会压下CS),即你所说的返回地址。你上文中提到的”也就是 call0080:08001200这种形式才会压入 CS“,而 ...
你真的想深入了解 x86 体系,好好的静下心来看看 amd/intel 官方的手册。
要想好好地学好每一条指令(如:call)要结合整个 x86 体系。
言归正题:
编译器不知道 call 到底是不是 far,只有 processor 才知道 call 是 far 还是 near... ...
现在的 OS 都是建立在 flat-segment memory 模式下(平垣模式),编译器都会将 call 编译为 near call 形式。只有在显式地写为“far call“时才是 farcall。
so. 无论你怎么引用外部的变量,函数,都是平坦的地址偏移量。
给你一个好的忠告:
你若真的要钻牛角下去。必须自己学会寻找答案。否则只要自寻苦恼。
回复 #8 mik 的帖子
mik,谢谢你的解答和建议。 同意LS几位,现在的CPU虽然支持分段机制,但是流行的OS,比如LINUX, WINDOWS根本就不用。所以很少能看到FAR CALL了。也许DOS会用FAR CALL?
PS:好像对 X86_64 的CPU,分段机制都没有了,只不过保留着那几个寄存器兼容老程序而已。
页:
[1]
2