Armv7 아키텍처에서 정의된 범용 레지스터 중 SP(R13) 레지스터와 LR(R14) 레지스터는 AAPCS와 연관된 핵심 레지스터입니다. 먼저 범용 레지스터 가운데 SP, LR 레지스터의 역할을 알아봅시다.

SP와 LR 레지스터의 역할

먼저 다음 그림을 보면서 Armv7 아키텍처에서 정의된 레지스터 중 AAPCS와 연관된 레지스터를 알아봅시다.

 
그림 12.1 Armv7 아키텍처의 레지스터 중 AAPCS와 연관된 레지스터 

위 그림은 Armv7 아키텍처에서 동작 모드별로 정의된 레지스터 목록입니다. 그림의 아랫부분에 빗금으로 표시된 부분을 봅시다.

해당 부분의 윗부분에 있는 SP 레지스터를 보겠습니다. 그림의 가장 왼쪽에 SP가 있는데, 같은 행에 각 동작 모드별로 SP_usr, SP_svc, SP_abt 레지스터가 있습니다. 그중 SP_svc는 슈퍼바이저 모드에서만 사용되는 SP 레지스터, SP_irq는 IRQ 모드에서만 접근하는 SP 레지스터입니다.

SP의 아랫부분을 보면 LR이 있는데, 이는 링크 레지스터(Link Register)를 나타냅니다. 보다시피 LR 레지스터 또한 각 동작 모드별로 존재합니다. 예를 들어, LR_svc는 슈퍼바이저 모드에서만 사용되는 LR 레지스터, LR_irq는 IRQ 모드에서만 접근되는 LR 레지스터입니다. 

[중요] 동작 모드별 뱅크드 레지스터

Armv7 아키텍처에서 각 동작 모드별로 뱅크드 레지스터가 존재합니다. 뱅크드 레지스터는 특정 동작 모드에서 전용으로 사용되는 레지스터입니다. 예를 들어 슈퍼바이저 모드에서 R13 레지스터가 바뀌면 R13_svc 레지스터가 함께 변경됩니다. 이와 마찬가지로 슈퍼바이저 모드에서 R14 레지스터가 바뀌면 R14_svc 레지스터가 함께 변경됩니다.

뱅크드 레지스터가 동작 모드별로 존재하면 동작 모드가 변경됐을 때 레지스터를 백업할 필요가 없어 간결하게 소프트웨어 구조를 설계할 수 있습니다. 


Arm 스펙 문서에서 본 SP 레지스터

이번에는 Arm 스펙 문서를 보면서 SP와 LR 레지스터에 대해 알아봅시다. 먼저 SP 레지스터에 대한 내용을 소개합니다.   

출처: ARM® Cortex™-A Series Programmer's Guide https://developer.arm.com/documentation/den0013/latest 
3.1 Registers
R13 (in all modes) is the OS stack pointer, but it can be used as a general purpose register when not required for stack operations.

위 내용은 다음과 같이 해석할 수 있습니다.

 R13은 운영체제의 스택 포인터(모든 모드에서 사용)다.
 R13은 스택 연산을 수행하지 않을 때 범용 레지스터처럼 사용될 수 있다.

그런데 Arm 스펙 문서의 내용 중 'OS stack pointer'로 적힌 부분이 있는데, 조금 포괄적인 의미를 지니고 있어 의도를 정확히 파악하기 어렵습니다. 여기서 'OS stack pointer'는 "프로세스의 스택 주소를 가리킨다"라고 해석하면 됩니다. 대부분의 운영체제는 프로세스 중심으로 실행되고, 어떤 함수나 레이블을 실행하거나 호출하던 프로세스의 스택 공간 내에서 실행되기 때문입니다. 

이어서 SP 레지스터에 대해 추가로 설명된 내용을 보겠습니다.

출처: ARM® Cortex™-A Series Programmer's Guide https://developer.arm.com/documentation/den0013/latest 
3.1 Registers
For example, a program executing in User mode which specifies R13 will access R13_usr. A program executing in SVC mode which specifies R13 will access R13_svc.

위 내용은 다음과 같이 요약할 수 있습니다.

유저 모드에서 실행되는 프로그램에서 R13을 지정하면 R13_usr가, 슈퍼바이저 모드에서 실행되는 프로그램에서 R13을 지정하면 R13_svc가 함께 업데이트된다.

Armv7 아키텍처에서 어떤 어셈블리 코드를 실행하든 동작 모드(슈퍼바이저, 유저 등등)에서 실행됩니다. 위 내용은 각 동작 모드에서 R13에 접근하면 해당 모드별로 정의된 R13 레지스터도 함께 액세스된다는 의미입니다. 이해를 돕기 위해 다음과 같은 예를 들겠습니다.

 유저 모드인 경우: R13 레지스터에 접근하면 R13_usr 레지스터에도 액세스
 슈퍼바이저 모드인 경우: R13 레지스터에 접근하면 R13_svc 레지스터에도 액세스

[정보] AAPCS의 핵심 원리와 디버깅

사실 위 내용을 읽으면 잘 와 닿지 않는데, TRACE32 같은 하드웨어 디버깅 장비를 사용해 확인하면 바로 이해할 수 있습니다. 다음 동영상 링크를 보면 TRACE32로 각 모드별로 R13 레지스터에 접근하는 내용을 확인할 수 있습니다. 
- TRACE32로 프로세스의 cpu_context(컨텍스트) 확인해보기: - https://youtu.be/pObn1fb-1M0


Arm 스펙 문서에서 본 LR 레지스터

이어서 스펙 문서 분석을 통해 LR 레지스터에 대해 알아봅시다.

출처: ARM® Cortex™-A Series Programmer's Guide https://developer.arm.com/documentation/den0013/latest 
3.1 Registers 
R14 (the Link Register) holds the return address from a subroutine entered when you use the branch with link (BL) instruction. It too can be used as a general purpose register when it is not supporting returns from subroutines. 

LR 레지스터를 명쾌하게 설명했는데, 내용을 요약하면 다음과 같습니다.

 LR은 BL 명령어와 함께 서브루틴(함수, 레이블) 주소로 분기했을 때 서브루틴에서 복귀할 주소를 저장하는 레지스터다.
 서브루틴으로 복귀하는 상황이 아니면 범용 레지스터로 사용될 수 있다.


[정보] 서브루틴이란?

Arm 스펙 문서를 보면 서브루틴(subroutine)이란 용어가 보입니다.

출처: https://developer.arm.com/documentation/dui0473/c/writing-arm-assembly-language/subroutines-calls
Subroutines calls
A subroutine is a block of code that performs a task based on some arguments and optionally returns a result. By convention, registers R0 to R3 are used to pass arguments to subroutines, and R0 is used to pass a result back to the callers. A subroutine that needs more than 4 inputs uses the stack for the additional inputs.

위 스펙은 Armv7 기반으로 서브루틴 호출(subroutines call)을 설명합니다. 여기서 서브루틴은 함수 호출이나 레이블로 분기하는 동작을 포함하며, 일반적으로 함수 호출을 서브루틴으로 표현할 때가 많습니다. 


SP 레지스터와 마찬가지로 LR 레지스터도 각 모드별로 LR_<mode> 레지스터가 존재합니다. 예를 들면 다음과 같습니다.

 IRQ 모드인 경우: R14 레지스터에 접근하면 R14_irq 레지스터에도 액세스
 슈퍼바이저 모드인 경우: R14 레지스터에 접근하면 R14_svc 레지스터에도 액세스

[중요] 동작 모드별로 SP 레지스터와 LR 레지스터가 존재하는 이유

Arm 프로세서에 대해 깊게 분석하면 동작 모드별로 SP와 LR 레지스터가 존재하는 이유를 알게 됩니다. 그 이유는 다음과 같이 설명할 수 있습니다. 

SP 레지스터와 LR 레지스터는 동작 모드별로 실행되는 프로세스의 실행 흐름을 저장하는 중요한 역할을 수행한다.

동작 모드를 변경하면 이전 동작 모드에서 실행됐던 레지스터를 어딘가에 백업해야 합니다. 그런데 각 동작 모드별로 SP 레지스터나 LR 레지스터가 없으면 동작 모드별로 실행된 레지스터를 스택과 같은 메모리 공간에 백업하고 로딩하는 루틴이 실행돼야 합니다. 그 결과, 시스템의 복잡도가 늘어납니다. 그래서 프로세스의 실행 흐름 정보를 저장하는 SP와 LR 레지스터가 각 동작 모드별로 존재합니다.


이처럼 SP와 LR 레지스터는 Armv7 아키텍처에서 정의된 다른 범용 레지스터와는 달리 서브루틴을 호출하기 위해 사용됩니다. 단순히 어셈블리 명령어를 실행한 결과를 저장하는 임시 저장용 메모리 공간은 아닙니다.

SP와 LR 레지스터의 표기 방식과 주요 동작 정리

이번에는 SP와 LR 레지스터의 표기 방식과 주요 동작을 표로 정리해 보겠습니다.

표 12.1 SP와 LR 레지스터의 특징
레지스터 특징
SP(Stack Pointer)  - R13으로도 표기
- 사용 중인 (프로세스의) 스택 위치를 저장 
- 동작 모드별로 SP 레지스터가 존재

LR(Link Register) - R14로도 표기
- 서브루틴을 수행(함수 호출)한 후 복귀할 주소를 저장 
- 동작 모드별로 LR 레지스터가 존재


어셈블리 명령어 중에서 SP(R13)와 LR(R14) 레지스터를 보면 위 표의 내용이 머릿속에 떠올랐으면 좋겠습니다.

+ Recent posts