예전에 제가 켈프 강좌에서 썼던 글입니다.
결론은 맨 마지막 줄입니다.

arm용에서 gcc는 스택포인터는 감소시키는가?
===========================================

1. 개요

이 문서는 ARM용으로 작성된 함수들은 스택 포인터가
감소하는가 증가 하는가를 조사한 문서이다.

2. 검증 과정 및 결과

ARM 의 구조는 스택 포인터에 관련된 명령이 따로 존재하지 않는다.
대신에 r13번이 스택포인터로 사용된다.

그렇기 때문에 스택을 감소 시키는 구조로 관리할지
증가 시키는 구조로 관리할지는 프로그래머의 맘이다.

그렇다면 gcc로 컴파일되는 실행코드의 스택관리는 어떤식으로
되었있느가에 대한 검증이 필요했다.

본인이 부트로더를 작성하면서
스택이 감소를 택하는지 증가를 택하는지를 검증하는
것은 중요했다.

이것을 검증하기 위해서

다음과 같은 프로그램을 작성했다.

int testsum( int a, int b )
{
return a, b;
}

int testfunc( int a, int b )
{
int sum;

sum = testsum( 1, 2 );

return sum;
}

이것을 어셈블러로 보면 다음과 같다.

======= test1.s ================================================
test1.o: file format elf32-littlearm

Disassembly of section .text:

00000000 :
0: e1a0c00d mov r12, sp
4: e92dd800 stmdb sp!, {r11, r12, lr, pc}
8: e24cb004 sub r11, r12, #4 ; 0x4
c: e24dd008 sub sp, sp, #8 ; 0x8
10: e50b0010 str r0, [r11, -#16]
14: e50b1014 str r1, [r11, -#20]
18: e51b3014 ldr r3, [r11, -#20]
1c: e1a00003 mov r0, r3
20: ea000007 b 44
24: e91ba800 ldmdb r11, {r11, sp, pc}

00000028 :
28: e1a0c00d mov r12, sp
2c: e92dd800 stmdb sp!, {r11, r12, lr, pc}
30: e24cb004 sub r11, r12, #4 ; 0x4
34: e24dd00c sub sp, sp, #12 ; 0xc
38: e50b0010 str r0, [r11, -#16]
3c: e50b1014 str r1, [r11, -#20]
40: e3a00001 mov r0, #1 ; 0x1
44: e3a01002 mov r1, #2 ; 0x2
48: ebfffffe bl 48
4c: e1a03000 mov r3, r0
50: e50b3018 str r3, [r11, -#24]
54: e51b3018 ldr r3, [r11, -#24]
58: e1a00003 mov r0, r3
5c: ea000016 b bc
60: e91ba800 ldmdb r11, {r11, sp, pc}
Disassembly of section .data:
======= test1.s ================================================

이문장에서 다음을 유심히 보아야 한다.

stmdb sp!, {r11, r12, lr, pc}

이 문장이 스택을 관리하는 방법에 대한 것이다.

이 문장을 해석하면

sp가 가리키는 주소에 r11, r12, lr, pc를 차례로
저장하라는 의미이다.

이때 sp에 !부호가 붙어 있으므로 sp값이
저장될때마다 변한다는 의미이며

sp가 증가 되는가 감소되는가는 stmdb의 접미사
를 보면 db라고 되어 있는데 이것은
감소라는 의미 이므로

sp는 데이타가 저장될때마다 감소한다는 것을
알수 있다.

결론은 간단하다 gcc에서는 스택 포인터를
저장할때마다 감소 시킨다.