System Programming(ARM)

4. Advanced ARM Instructions

suhwanc 2020. 12. 15. 19:59

이번엔 좀 더 어려운 arm 명령어 ldr/str 그리고 stack에 대해 알아보자.

 

 

1. LDR / STR with offsets

 

기본적으로 arm에서 메모리를 참조하는 연산은 LDR/STR이 전부이다.

이 명령어들에는 offset이 포함되는데, offset의 위치에 따라 기능이 다르다.(바로 뒤에 설명)

 

1) pre-indexed format

 

LDR / STR Basic Format

pre-indexed format은 offset의 위치가 base register(rn) 과 같은 괄호 안에 포함되어있을 경우이다.

 

예를 들어 ldr r0, [r1, #12] , str r5, [r6, r7, lsl #2] 와 같은 경우 pre-indexed 라고 할 수 있겠다.

pre-indexed는 rn의 값을 offset으로 이동한 위치에 있는 값을 연산한다는 의미인데,

만약 ldr r0, [r1, #12] 라면, r1 + 12 에 있는 메모리 값을 r0으로 로드한다는 의미이다.

 

또한 맨 뒤 {!} 표시가 있는데, 뒤에 느낌표가 붙는다면, base register(rn)의 값을 offset 만큼 변경시킨다는 의미를 갖는다.

 

2) post-indexed format

Post-indexed Format

post-indexed format은 offset 의 위치가 rn과 다른 괄호에 위치한다.

이 방법은 "연산 후 변경" 이라고 하는데, 먼저 rn에 있는 값을 rd에 대입한 후 offset만큼 움직여주면 된다.

 

 

2. LDR with Labels

 

LDR에 Label이 붙은 경우는 32비트 상수를 처리할 수 있게 한다.

위 경우, label에 상수가 들어있는 상태이다.

해당 명령어를 처리할 때는 ldr rd, [pc, <상대 주소 값>] 으로 처리되기 때문에 이후 배울 2pass 어셈블러 단계에서 해당 라벨을 주소와 함께 특정 테이블로 묶고, 나중에 주소를 불러와 간접적으로 처리하게 된다.

여기서 중요한건 너무 멀리 떨어져 있는 label은 안된다는 점이다.

 

 

3. 블록 단위의 스택 연산

 

arm에서 스택은 아주 중요한 역할을 한다. 이는 프로시저 단계에서 더 많이 배울 텐데 그전에 스택에 여러 원소를 한꺼번에 넣고 빼는 방법을 알아보자.

 

명령어 형식은 다음과 같다.

 

STM은 stack에 여러개를 push 하는 명령어이고 LDM은 stack에 있는 여러 원소를 한꺼번에 pop 하는 명령어이다.

 

보통 FA, FD를 많이 사용하는데, 4가지 경우는 아래 그림을 참조하자.

왼쪽부터 차례대로 설명하자면

 

1) STMFD : Stack Multiple Full Descending

 

기존 stack pointer(old sp)를 비우고, 뒤에서 부터(r5,r4,r3,r1,r0) 한 칸씩 내려가면서 채운다. 마지막 sp는 내리지 않고 그대로 둔다.

 

2) STMED : Stack Multiple Empty Descending

 

기존 stack pointer(old sp)를 채우고, 뒤에서 부터(r5,r4,r3,r1,r0) 한 칸씩 내려가면서 채운다. 마지막 sp는 비운다.

 

3) STMFA : Stack Multiple Full Ascending

 

기존 stack pointer(old sp)를 비우고, 앞에서 부터(r5,r4,r3,r1,r0) 한 칸씩 올라가면서 채운다. 마지막 sp는 올리지 않고 그대로 둔다.

 

4) STMEA : Stack Multiple Empty Ascending

 

기존 stack pointer(old sp)를 채우고, 앞에서 부터(r5,r4,r3,r1,r0) 한 칸씩 올라가면서 채운다. 마지막 sp는 비운다.

 

 

스택 컨벤션

 

STMFD sp!, {r0-r3} 은 push {r0-r3} 과 같다.

LDMFD sp!, {r0-r3} 은 pop {r0-r3} 과 같다.

 

 

4. 곱셈 명령어

 

이번엔 누구나 아는 곱셈이지만 Data processing 명령어에 포함되지 않은, 꽤나 유니크한 명령어 곱셈 명령어이다.

 

형태는 다음과 같다.

 

ARM Multiplication Instructions

MUL은 그대로 rd에 rm x rs 를 한 결괏값을 대입하는 것이고

MLA는 뒤에 Add가 붙어서, MUL 연산에 맨 뒤 rn 레지스터를 더하는 것이다.

 

이때 주의할 것은 rd와 rm은 같은 레지스터가 될 수 없다는 점이다. 

왜 그런가 찾아보니 그냥 규정이 그렇다고 한다. 또한 곱셈 명령어는 pc(program counter)를 사용할 수 없다.