当前位置: 技术问答>linux和unix
有一个参数在栈中传递的问题
来源: 互联网 发布时间:2015-05-22
本文导语: 简单编一个main.c,main函数内调用一个my_nop(int *)函数,该函数如下: #include int my_nop(int *a){ int i=1; (*a) += i; return 0; } int main(int argc,char *argv[]){ int j=0; ...
简单编一个main.c,main函数内调用一个my_nop(int *)函数,该函数如下:
#include
int my_nop(int *a){
int i=1;
(*a) += i;
return 0;
}
int main(int argc,char *argv[]){
int j=0;
j += my_nop(&j);
return 0;
}
编译成后,用objdump看到my_nop函数部分如下:
:
55 push %ebp
89 e5 mov %esp,%ebp
83 ec 04 sub $0x4,%esp
c7 45 fc 01 00 00 00 movl $0x1,0xfffffffc(%ebp)
8b 4d 08 mov 0x8(%ebp),%ecx
8b 55 08 mov 0x8(%ebp),%edx
8b 45 fc mov 0xfffffffc(%ebp),%eax
03 02 add (%edx),%eax
89 01 mov %eax,(%ecx)
b8 00 00 00 00 mov $0x0,%eax
c9 leave
c3 ret
可以看出,main函数在调用my_nop函数之前,把参数j的地址放在栈中,进入my_nop函数后,ebp和esp首先被调整,在my_nop内部,用ebp的值加8作为地址,去取main函数先前放置在栈中的参数j的地址。让我感到困惑的是这句:
add (%edx),%eax 和
mov %eax,(%ecx)
ecx、edx寻址,其段基址是由DS给出的,而j其实是存放在栈中的(main的局部变量),我觉得应该是
add ss:(%edx),%eax 和
mov %eax,ss:(%ecx)
我错在哪里?难道linux中SS=DS?
请知情者不吝赐教!
#include
int my_nop(int *a){
int i=1;
(*a) += i;
return 0;
}
int main(int argc,char *argv[]){
int j=0;
j += my_nop(&j);
return 0;
}
编译成后,用objdump看到my_nop函数部分如下:
:
55 push %ebp
89 e5 mov %esp,%ebp
83 ec 04 sub $0x4,%esp
c7 45 fc 01 00 00 00 movl $0x1,0xfffffffc(%ebp)
8b 4d 08 mov 0x8(%ebp),%ecx
8b 55 08 mov 0x8(%ebp),%edx
8b 45 fc mov 0xfffffffc(%ebp),%eax
03 02 add (%edx),%eax
89 01 mov %eax,(%ecx)
b8 00 00 00 00 mov $0x0,%eax
c9 leave
c3 ret
可以看出,main函数在调用my_nop函数之前,把参数j的地址放在栈中,进入my_nop函数后,ebp和esp首先被调整,在my_nop内部,用ebp的值加8作为地址,去取main函数先前放置在栈中的参数j的地址。让我感到困惑的是这句:
add (%edx),%eax 和
mov %eax,(%ecx)
ecx、edx寻址,其段基址是由DS给出的,而j其实是存放在栈中的(main的局部变量),我觉得应该是
add ss:(%edx),%eax 和
mov %eax,ss:(%ecx)
我错在哪里?难道linux中SS=DS?
请知情者不吝赐教!
|
是的。你可以看看Linux的启动源代码的初始化GDT表的部分
具体的代码我给你贴一下吧
/usr/src/linux-2.4/arch/i386/kernel/head.S
----------------------------------------------------------
ENTRY(gdt_table)
.quad 0x0000000000000000 /* NULL descriptor */
.quad 0x0000000000000000 /* not used */
.quad 0x00cf9a000000ffff /* 0x10 kernel 4GB code at 0x00000000 */
.quad 0x00cf92000000ffff /* 0x18 kernel 4GB data at 0x00000000 */
.quad 0x00cffa000000ffff /* 0x23 user 4GB code at 0x00000000 */
.quad 0x00cff2000000ffff /* 0x2b user 4GB data at 0x00000000 */
.quad 0x0000000000000000 /* not used */
.quad 0x0000000000000000 /* not used */
/*
* The APM segments have byte granularity and their bases
* and limits are set at run time.
*/
.quad 0x0040920000000000 /* 0x40 APM set up for bad BIOS's */
.quad 0x00409a0000000000 /* 0x48 APM CS code */
.quad 0x00009a0000000000 /* 0x50 APM CS 16 code (16 bit) */
.quad 0x0040920000000000 /* 0x58 APM DS data */
.fill NR_CPUS*4,8,0 /* space for TSS's and LDT's */
----------------------------------------------------------------------------
注意 .quad 0x00cf9a000000ffff /* 0x10 kernel 4GB code at 0x00000000 */
.quad 0x00cf92000000ffff /* 0x18 kernel 4GB data at 0x00000000 */
.quad 0x00cffa000000ffff /* 0x23 user 4GB code at 0x00000000 */
.quad 0x00cff2000000ffff /* 0x2b user 4GB data at 0x00000000 */
应该写的很清楚了吧?
具体的代码我给你贴一下吧
/usr/src/linux-2.4/arch/i386/kernel/head.S
----------------------------------------------------------
ENTRY(gdt_table)
.quad 0x0000000000000000 /* NULL descriptor */
.quad 0x0000000000000000 /* not used */
.quad 0x00cf9a000000ffff /* 0x10 kernel 4GB code at 0x00000000 */
.quad 0x00cf92000000ffff /* 0x18 kernel 4GB data at 0x00000000 */
.quad 0x00cffa000000ffff /* 0x23 user 4GB code at 0x00000000 */
.quad 0x00cff2000000ffff /* 0x2b user 4GB data at 0x00000000 */
.quad 0x0000000000000000 /* not used */
.quad 0x0000000000000000 /* not used */
/*
* The APM segments have byte granularity and their bases
* and limits are set at run time.
*/
.quad 0x0040920000000000 /* 0x40 APM set up for bad BIOS's */
.quad 0x00409a0000000000 /* 0x48 APM CS code */
.quad 0x00009a0000000000 /* 0x50 APM CS 16 code (16 bit) */
.quad 0x0040920000000000 /* 0x58 APM DS data */
.fill NR_CPUS*4,8,0 /* space for TSS's and LDT's */
----------------------------------------------------------------------------
注意 .quad 0x00cf9a000000ffff /* 0x10 kernel 4GB code at 0x00000000 */
.quad 0x00cf92000000ffff /* 0x18 kernel 4GB data at 0x00000000 */
.quad 0x00cffa000000ffff /* 0x23 user 4GB code at 0x00000000 */
.quad 0x00cff2000000ffff /* 0x2b user 4GB data at 0x00000000 */
应该写的很清楚了吧?