2017-04-10 10 views
2

그래서 extern C 함수를 호출하는 어셈블리 프로그램을 작성해야합니다. 그래서 간단한 pow 함수를 작성 했으므로이 C 코드로 어셈블리 프로그램을 컴파일했습니다. 모든 것이 작동합니다. 그러나 -S 명령 (gcc)에서 알 수 있듯이 컴파일러는 로컬 변수를위한 공간을 만듭니다.어셈블리에서 로컬 변수를위한 공간 만들기

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 지금은 내 코드가 있습니다. 하지만 지금은 subl의 항목이 없습니다. %esp. 이 줄을 추가 할 수는 있지만 아무 것도 변경하지 않습니다. 나는 인터넷을 통해 조사한 결과 실수로 코드가 작동하고 일반적으로 감소해야한다고 알았습니다. %esp. 그래서 내 질문은 여기에 있습니다 : main에 어떤 값을 내서 %esp을 감소시켜야합니까? 12이거나 16일까요?

+4

'의 사용 16' 정렬 된 스택을 16 바이트를 유지할 가능성이 높다. – unwind

+0

당신이 옳은 것 같아요,하지만 항상 16 바이트 정렬을해야합니까, 아니면 특정 값을'subl'해야합니까? – Frynio

+1

요구 사항은 플랫폼의 ABI (Application Binary Interface) 설명서에 지정되어있을 수 있습니다. 스펙이므로 다른 코드와 상호 작용할 수 있도록해야합니다. – unwind

답변

0

32 비트 C 함수를 호출하기 때문에 C calling convention을 따라야합니다. 64 비트 시스템과 달리 스택을 정렬하기위한 명시적인 순서는 없습니다. 나는와 같은 정렬이 일어날 때 성명을 찾을 수 없었다. 매개 변수를 누르면 스택이 "잘못 정렬"될 수 있습니다.

당신은 스택을 정렬 할 경우 할 수있는 간단하고 -16 당신이 그것을 (movl %esp, %ebp)을 저장 한 후 :

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

이것은 C 코드를 컴파일 할 때'gcc '가하는 것과 정확히 같습니다. 음, 그렇지만 지역 변수를위한 공간을 만들기 위해 esp에서 무엇이든지'subl'해야합니까? – Frynio

+0

지역 변수 (필요한 경우)에 대한 첫 번째'subl ', 그리고 정렬을위한'andl'.그러나 32 비트 C에서 16 바이트 정렬이 필요 없다고 확신합니다. – rkhb

+0

좋아요, 필요 없다는 것을 알고 있습니다. 그러나'gcc'는 몇몇 값을'subl'하지만,'addl'으로 값을 정렬하지 않습니다. 내 말은 '떠나라'는 지시와 함께한다는 뜻입니다. 그러나 여기에있는 질문은 - 나는'% esp'에서 무엇인가'서브'해야합니까? – Frynio