局部变量的堆栈顺序的疑惑,来自《汇编语言程序设计》一书

gzshun 2017-03-29 09:02:13
我在阅读马朝晖翻译的《汇编语言程序设计》,在第11章“使用函数”这张,看到图11-6,我这里使用文字描述堆栈结构:
图11-6 堆栈顺序如下:

函数参数3 -> 16(%ebp)
函数参数2 -> 12(%ebp)
函数参数1 -> 8(%ebp)
返回地址 -> 4(%ebp)
旧的EBP值 -> (%ebp)
局部变量1 -> -4(%ebp)
局部变量2 -> -8(%ebp)
局部变量3 -> -12(%ebp)

首先x86的栈空间地址是从高地址到低地址,但是对于图11-6中的描述,我觉得局部变量1应该在-12(%ebp)才对,为什么书上会这么写?

我做了个实验,c语言代码如下:

#include <stdio.h>

void fun()
{
int aa = 1;
int bb = 2;
int cc = 3;
}

int main()
{
fun();
return 0;
}

编译转换成汇编,fun函数如下:

080483db <fun>:
80483db: 55 push %ebp
80483dc: 89 e5 mov %esp,%ebp
80483de: 83 ec 10 sub $0x10,%esp
80483e1: c7 45 f4 01 00 00 00 movl $0x1,-0xc(%ebp)
80483e8: c7 45 f8 02 00 00 00 movl $0x2,-0x8(%ebp)
80483ef: c7 45 fc 03 00 00 00 movl $0x3,-0x4(%ebp)
80483f6: 90 nop
80483f7: c9 leave
80483f8: c3 ret

从这个实验可以看出,int aa = 1这行对应的汇编是 movl $0x1,-0xc(%ebp),这里正好说明局部变量1是在栈顶,也就是最低的地址,堆栈结构是这样:

函数参数3 -> 16(%ebp)
函数参数2 -> 12(%ebp)
函数参数1 -> 8(%ebp)
返回地址 -> 4(%ebp)
旧的EBP值 -> (%ebp)
局部变量3 -> -4(%ebp) //cc
局部变量2 -> -8(%ebp) //bb
局部变量1 -> -12(%ebp) //aa

从实验来看,越靠后的局部变量,地址越高,越靠近esp。我现在有这个疑惑,实验结果正好跟书上相反,哪个才是正确的?
...全文
269 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
gzshun 2017-03-30
  • 打赏
  • 举报
回复
引用 1 楼 zara 的回复:
环境不一样编译器不同,做法上也可能有异吧。看你这个的写法,是 unix 类的?而且,你那个堆栈结构的写法也别扭,顺序上倒了,通常是低地址在上,高地址在下。 刚才试了下 Windows/VC2008 生成的代码,和你书上的是一致的:
PUBLIC	?fun@@YAXXZ					; fun
; Function compile flags: /Odtp
_TEXT	SEGMENT
_bb$ = -12						; size = 4
_cc$ = -8						; size = 4
_aa$ = -4						; size = 4
?fun@@YAXXZ PROC					; fun
; File r:\kc1.cpp
; Line 4
	push	ebp
	mov	ebp, esp
	sub	esp, 12					; 0000000cH
; Line 5
	mov	DWORD PTR _aa$[ebp], 1
; Line 6
	mov	DWORD PTR _bb$[ebp], 2
; Line 7
	mov	DWORD PTR _cc$[ebp], 3
; Line 8
	mov	esp, ebp
	pop	ebp
	ret	0
?fun@@YAXXZ ENDP					; fun
你好,我在linux平台实验,汇编是AT&T语法,使用的是gcc编译器,这本书画的图都是高地址在上,看来不同平台不同编译器的结果是不一样的,我大概了解了,谢谢。
zara 2017-03-30
  • 打赏
  • 举报
回复
环境不一样编译器不同,做法上也可能有异吧。看你这个的写法,是 unix 类的?而且,你那个堆栈结构的写法也别扭,顺序上倒了,通常是低地址在上,高地址在下。
刚才试了下 Windows/VC2008 生成的代码,和你书上的是一致的:
PUBLIC	?fun@@YAXXZ					; fun
; Function compile flags: /Odtp
_TEXT SEGMENT
_bb$ = -12 ; size = 4
_cc$ = -8 ; size = 4
_aa$ = -4 ; size = 4
?fun@@YAXXZ PROC ; fun
; File r:\kc1.cpp
; Line 4
push ebp
mov ebp, esp
sub esp, 12 ; 0000000cH
; Line 5
mov DWORD PTR _aa$[ebp], 1
; Line 6
mov DWORD PTR _bb$[ebp], 2
; Line 7
mov DWORD PTR _cc$[ebp], 3
; Line 8
mov esp, ebp
pop ebp
ret 0
?fun@@YAXXZ ENDP ; fun
gzshun 2017-03-30
  • 打赏
  • 举报
回复
引用 3 楼 DelphiGuy 的回复:
与编译器有关,与优化选项有关,总之不能保证局部变量的声明顺序和存储顺序一致,一般来说,Borland C++、ms VC++按照声明顺序从高地址向低地址排列,intel C++、gcc/g++则相反,按照声明顺序从低地址向高地址排列。
学习了,谢谢
  • 打赏
  • 举报
回复
与编译器有关,与优化选项有关,总之不能保证局部变量的声明顺序和存储顺序一致,一般来说,Borland C++、ms VC++按照声明顺序从高地址向低地址排列,intel C++、gcc/g++则相反,按照声明顺序从低地址向高地址排列。

21,459

社区成员

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

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