为程序集中的局部变量创建空间

问题描述:

所以我必须编写一个调用extern C函数的汇编程序。所以我写了简单的pow函数,我用这个C代码编译我的汇编程序。一切正常。但正如我从gcc-S命令看到的那样,编译器为局部变量创建了一个空间。我认为它会是这样的:为程序集中的局部变量创建空间

int func(int number) 
{ 
    int a = 10; 
    int b = 5; 
    int c = 0; 
} 

我们有3个局部变量,所以编译器会subl $12, %esp。但它适用于subl $16, %esp。即使我在这里只留下一个数字,它仍会减少16。现在,我有我的代码:

main.s

.section .data 
.XD: 
    msg: .ascii "%d\n" 
    msg_len = . - msg 

.text 
.globl _pow 
.globl main 

main: 
    pushl %ebp 
    movl %esp, %ebp 
    movl $5, %eax #like int a = 5; 
    pushl %eax 
    call _pow #_pow(a); 
    movl %eax, -8(%ebp) 
    pushl -8(%ebp) 
    pushl $.XD 
    call printf #printf("%d\n", _pow(a)); 
    movl $0, %eax 
    leave 
    ret 

func.c

int _pow(int number) 
{ 
    return number * number; 
} 

它按预期工作,./main打印出25。但是现在,我没有任何东西从%esp。我的意思是我可以添加这一行,但它不会改变任何东西。我通过互联网搜索,发现也许我的代码只是偶然的工作,通常我应该递减%esp。所以我的问题在于:通过main,我应该减少%esp的值?应该是12还是16

+4

采用'16'很可能保持一致堆栈16字节。 – unwind

+0

我想你是对的,但是我应该让它总是16字节对齐,还是应该subl特定值? – Frynio

+1

该要求可能在平台的应用程序二进制接口(ABI)文档中指定。既然它是一个规范,你应该遵循它以便能够与其他代码交互。 – unwind

由于您正在调用32位C函数,因此您必须遵循C calling convention。与64位系统不同,没有明确的对齐堆栈的顺序。我找不到这样一个对齐应该发生的声明。按下参数后堆栈可能“未对齐”。

如果你要对齐的堆栈,你可以简单-16后,你救了它(movl %esp, %ebp):

andl $-16, %esp    ; Align 16 
+0

编译C代码时,这正是'gcc'所做的。嗯,但那么我应该''subl'什么从esp,为局部变量的空间? – Frynio

+0

第一个'subl'用于局部变量(如果需要的话),然后''andl'用于对齐。不过,我确信你不需要32位C的16字节对齐方式。 – rkhb

+0

好的,我知道我不需要它。但是'gcc'确实subl'有一些值,但是它不会与'addl'iing对齐。我的意思是它 - 用“离开”指令。但是这里的问题是 - 我是否需要从'%esp'中'subl'任何东西? – Frynio