MIPS 레지스터
MIPS 레지스터는 2개의 읽기 포트와 1개의 쓰기 포트로 구성되어 있습니다.
즉, 주소 읽기 포트와 데이터 읽기 포트가 각각 2개씩, 그리고 주소 쓰기 포트와 데이터 쓰기 포트가 각각 1개씩 존재합니다.
주소 포트는 주소 버스에 대해 2^n
의 n개 포트만 필요하므로 총 5개의 포트가 필요하며, 데이터 포트는 데이터 버스에 n개의 포트가 필요하므로 총 32개의 포트가 필요합니다.
그래서 동일한 시간에 2개의 레지스터에서 데이터를 읽어올 수 있지만, 데이터를 쓸 때는 하나의 레지스터에만 쓸 수 있습니다.
레지스터 테이블
zero
는 0만 고정되는 레지스터입니다. 한 레지스터의 값을 그대로 다른 레지스터에 대입, 0을 대입시킬 때 또는 nor
연산에서 not
을 표현하기 위해 사용합니다.
at
은 어셈블러에 의해 사용됩니다.
v0
, v1
은 함수 반환값에 사용하는 레지스터입니다.
그런데 C언어에서 함수의 반환 값은 무조건 없거나 1개입니다. 그런데 왜 return values는 2개의 레지스터를 사용할까요? 그 이유는 32비트 아키텍쳐인 MIPS에서 64비트 정수형을 다루기 위해서 입니다.
a0 - a3
은 함수의 인자를 저장하기 위한 레지스터입니다. 여기도 의문점이 있습니다. 레지스터가 4개뿐이라 함수의 인자는 최대 4개만 저장할 수 있습니다. 함수의 인자 개수가 5개 이상인 경우에는 스택을 사용합니다.
t0 - t9
까지는 임시로 저장할 값을 위한 레지스터인데 그 사이에 s0 - s7
까지 저장용 레지스터가 위치하고 있습니다.
레지스터 26, 27은 커널용(k)으로 할당되어서 일반적으로 접할 일이 없습니다.
$ra
: 원래의 위치로 돌아가 위해서 원래의 주소를 저장하는 데 사용하는 레지스터가 하나 더 필요하기 때문입니다. 복귀 주소(return address)를 의미합니다.
스택 사용 (sp)
callee는 인자가 5개 이상인 경우, 작업을 수행하기 위해서 메모리의 스택 영역을 사용합니다.
레지스터에 모든 인자를 저장할 수 없기 때문에 메모리의 스택 영역에 저장한 후, 필요한 경우 메모리에 접근해서 $sp
레지스터로 그 값을 불러 옵니다.
- push
프레임 포인터 레지스터 (fp)
$fp
는 스택의 한 프레임이 시작하는 위치를 가리키는 레지스터입니다. base 주소를 의미한다고 이해할 수 있습니다.
새로운 함수로 진입할 때는 $fp
에 이전 sp 값 - 4를 저장합니다.
이동할 때, 기존의 $fp
값을 따로 백업해 두어야지만 함수가 종료되었을 때 원래의 위치로 돌아갈 수 있습니다.
함수에서 스택에 할당한 지역변수들은 해당 함수가 종료될 때 같이 사라지므로(pop) 프로그램의 크기에 영향을 끼치지 않습니다.
힙 사용 (gp)
힙은 스택과 반대로 낮은 주소부터 위로 커집니다.
Procedure
Procedure은 특정 task를 수행하기 위한 명령어 집합을 의미합니다.
-
Caller
procedure를 호출하는 대상
-
Callee
procedure에 의해 호출 당하는 대상
보존하는 대상 |
호출후 보존 여부 |
설명 |
---|---|---|
Caller | Yes | Caller-saved s 레지스터가 부족해서 t 레지스터에 저장해야 한다면, t 값들을 미리 백업 non-volatile-reg 함수 호출 전후의 값 변화가 없음 |
Callee | No | Callee-saved s 레지스터 따로 백업한 뒤, s 레지스터들을 사용하고, 백업한 값들로 이전의 s 레지스터 값들을 원상복구시키고 종료 t는 막 사용 volatile-reg |
MIPS는 32비트 레지스터로 되어있어 32비트보다 큰 데이터들은 메모리에 저장합니다.
메모리에 접근하는 방식은 메모리 접근 글에서 볼 수 있습니다.
이떻게 procedure로 이동하고 돌아오는지는 분기 명령어인 jal
, jr
을 이해해야 합니다.
-
Leaf procedure
다른 함수를 호출하지 않는 함수