2017-04-10 48 views
2

所以我必須編寫一個調用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

回答

0

由於您正在調用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