ATPCS(ARM-Thumb Procedure Call Standard)
이는 함수의 전달인자와 리턴 어드레스(함수 호출이 완료되고 나면 돌아갈 주소)를 레지스터에 저장하기로 결정하고, 저장 방식에 대한 표준을 정의한 것이다. 이 표준을 고려하여 ARM코어의 레지스터들도 디자인 되어 있고, ARM컴파일러도 이 표준에 맞게 바이너리 코드를 생성하도록 디자인 되어있다.
스텍 프레임(Stack Frame)구조
함수 호출 과정에서 할당되는 메모리 블록(지역 변수 선언으로 인해 할당되는)을 가리켜 스택 프레임이라 한다. 위 그림을 보면 main함수에 변수 a와 b가 선언되어 있다. 따라서 스택에도 a, b가 할당되어 main 함수의 스택 프레임을 구성한다.
return에 의해 함수 호출이 완료되면 해당 함수의 지역변수에는 접근이 불가능하다. 할당되었던 메모리가 반환되었기 때문이다.
SP(Stack Pointer)레지스터
지역변수를 저장하는 메모리 공간을 스택이라 이름 붙이는 이유는 메모리의 구조적 특성(First In, First Out)때문이다.
스택 프레임은 가장 먼저 할당되면 가장 나중에 반환된다. 그리고 가장 나중에 할당되면, 가장 먼저 반환된다.
스택에 데이터를 쌓거나 반환하기 위해서는 현재 어느 위치까지 데이터를 저장했는지 기억해야 한다. 이것을 하는 것이 CPU내에 존재하는 SP(Stack Pointer)이다.
지역 변수는 a,b,c ... 순으로 스택에 할당된다. SP 레지스터 값은 이렇게 변수가 하나씩 할당될 때마다 증가한다. 증가하면서 다음 변수가 할당될 메모리 위치를 가리킨다. 함수가 종료할 때에도 SP레지스터 값을 이동시켜야 한다. 호출된 함수가 종료될 경우 그 함수 내에서 선언된 변수들을 동시에 모두 반환해야 하기 때문이다.
함수가 종료되고 스택 프레임 단위로 SP를 아래로 이동시킬 때는 얼마만큼 SP를 이동시켜야 하는지 알 수가 없다.
이를 해결해 주는 것이 프레임 포인터 레지스터이다.
프레임 포인터(Frame Pointer) 레지스터
되돌아갈(함수 호출 이전의) SP 위치를 저장해 놓으면 함수 반환시 스택 프레임 단위로 SP위치 조절이 가능하다. 이 역할을 하는 레지스터를 가리켜 fp(Frame Pointer)레지스터라 한다.
sp레지스터에 저장된 값을 fp레지스터에 저장하는 상황을 보여준다. fct1에서 많은 변수를 선언하더라도 fp에 저장된 값을 참조해서 fct1함수 호출 이전 위치로 sp를 이동시킬 수 있다.
스택프레임 포인터를 이용하여 정확히 함수의 스택 프레임만 반환할 수 있게 된 것이다.
fp 레지스터의 문제점
위처럼 두번쨰 함수 호출시 sp레지스터가 이전 fp값을 덮어버리기 때문에 문제가 발생한다. fct1의 값이 사라져 레지스터 값을 참조할 수 없게 된다.
스택에 저장하자, 프레임 포인터(Frame Pointer)
여러 함수를 호출할 때 fp를 덮어쓰는 문제점을 해결하는 방법은 덮어 쓰기 전에 fp에 저장된 값을 다른곳에 저장해 두는 것이다. 즉 함수 호출이 일어날 때마다 fp레지스터에 저아되어 있는 값을 스택에 저장하는 것이다. 그리고 이후에 새로운 값으로 fp레지스터를 채운다.
1.fct2함수가 호출되기 직전에 sp레지스터에는 주소값 20이 들어가 있다. 현재 스택 주소를 가리키는 것이다.
2.fct2함수가 호출되기 직전에 fp레지스터에는 주소값 8이 들어가 있다. fct1의 스택 프레임 포인터이다.
3.fct2 함수가 호출되면서, fp레지스터에 저장된 값(주소값 8)을 현재 sp레지스터가 가리키는 위치 20번지에 먼저 저장한다. 그다음 fp레지스터에 sp레지스터 값 20을 저장한다.
4.fct2 함수 호출이 완료되어 반환한다면, fp레지스터에 저장된 값을 참조해서 sp레지스터 값을 20으로 변경한다. 이는 fct2함수의 스택 프레임을 날리는 것이다.
5.현재 sp레지스터가 가리키는 위치(주소 20번지)에 저장되어 있는 값을 fp레지스터에 옮겨다 놓는다. 이로써 fct1함수 호출이 완료되는 상황에서 sp의 위치를 8번지에 가져다 놓을 수 있게 된다.
'Programming > Windows System Programming' 카테고리의 다른 글
함수 호출(Procedure Call)에 의한 실행의 이동 (0) | 2020.07.18 |
---|---|
함수 호출 인자의 전달과 PUSH & POP 명령어 디자인 (0) | 2020.07.16 |
스케줄링 알고리즘과 우선순위 (0) | 2020.07.13 |
파이프 방식의 IPC (0) | 2020.07.12 |
핸들 테이블과 오브젝트 핸들의 상속 (0) | 2020.07.11 |