조건부 명령
if / else와 같은 Arm 명령어이다.
CMP reg1, reg2 ; r1, r2를 비교해라 .
여기서 비교란 뺄셈을 하라는 의미이다. 만약 두 값이 같으면 두 값을 뺀값은 0이 될것이다. > zero flag
BEQ L1 ; 이전 계산이 0이면 L1으로 분기하라
BNE L1 ; 이전 계산이 0이 아니면 L1으로 분기하라
B exit ; 무조건 분기 하라
C code
if (i == j) f = g+h;
else f = g-h
Compiled ARM code
CMP r3, r4
BNE Else ; go to Else if i != j
ADD r0, r1, r2 = f = g+h(skipped if i != j)
B Exit
Else ; SUB r0, r1, r2 ; f = g + h (skipped if i = j)
Exit;
뛰어넘어야 될 위치에 대해서 라벨이 필요하다. Else, Exit
라벨을 다는 이유는 무엇일까? 생각을 해보면 라벨이 아니라 메모리 주소 번지수를 달아야 되는것이 아닌가? (포인터 처럼) 왜 숫자가 아닌 라벨을 다는 것일까 ?
일반적으로 프로그램은 하드디스크에 보관되어 있습니다. 즉, 프로그램이 실행되려면 하드디스크에서 메모리로 카피해온 다음 수행이 됩니다. 수행이 시작될때 메모리의 위치가 결정됩니다. 즉, 수행하기전 하드 디스크에서는 정확한 위치 결정이 되지 않기 때문에 상대적인 위치인 라벨을 다는 것입니다.
Compiling Loop Statements
C code
while ( save[i] == k ) i += 1;
- i in r3, k in r5, base address of save in r6
Compiled ARM code
Loop: ADD r12, r6, r3, LSL # 2 r3 왼쪽 2비트 시프트 (4배) ; r12 = save[i]의 주소
LDR r0, r[12, #0] ; Temp reg r0 = save[i]
CMP r0, r5
BNE Exit
ADD r3, r3 + #1 ; go to Exit if save[i] = k
B LOOP ; go to Loop
Exit;
Procedure Calling
C언어의 main함수에 모든 코드를 작성하지 않는다. main함수 중간중간에 필요에 맞는 함수들을 호출하여 효율성을 올린다. 즉 이러한 과정을 Calling이라 한다.
1. place parameters in registers
- 함수의 파라미터를 레지스터에 넣자.
2. Transfer control to procedure
- branch 분기해서 넘어가는 동작
3. Acquire storage for procedure
- 호출한 함수에 대한 메모리 공간이 필요하다 (함수 내의 변수 등등)
4. Perform procedure's operations
- 실제로 수행
5. Place result in register for caller
- 레지스터로 리턴값 받아라
6. Return to place of call
- 담은 다음 다시 점프해서 원래의 곳에 돌아와라
main 함수를 생각해보자. main 함수내에서 어떤 연산을 수행하던 와중 중간에 함수를 호출해야되는 상황에 마추쳤다. 이제까지 연산 해 왔던 데이터들의 입장에서 이 값들은 레지스터에 계속 저장하고 싶어 할 것이다. 하지만 호출되는 함수입장에서도 호출에 필요한 데이터들이 저장되는 레지스터가 필요할 것이다. 이렇게 하나의 레지스터에 여려 데이터 값들이 맞물려 돌아가는 상황을 어떻게 효율적으로 처리할 것인가 ?
레지스터 사용법에 대한 규칙을 약속하자.
0~1번은 a1, a2라 이름 붙이자 argument로 쓰자 (파라미터로 쓰자.) / return result
2~3번은 a3, a4라 쓰자. Argument
4~11번은 v라 이름 붙이자. 변수에 사용하는 레지스터 계산하는 값들이 저장된다. 호출된 함수를 위해 레지스터를 쓰려면 원래 있던 값들을 메모리에 카피해 놨다가 이제 빈 레지스터로 호출된 함수를 위해 사용한다. 호출한 함수를 다 수행하고 리턴해온 값을 반환할때 카피한 값들을 메모리에서 다시 레지스터로 가져온다. 즉, 메모리로 카피를 해야되기 때문에 보존을 잘 해야된다.
12 ~ 15번은 특별한 용도의 레지스터
15번 : 프로그램을 수행하는 위치를 저장한다.
14번 : 링크 레지스터이며, 내가 돌아온 주소를 저장한다. 즉, 프로그램 수행 중 분기 될때 돌아올 값을 저장한다.
13번 : 스택 포인터, 레지스터의 구조가 스택 형식으로 되면 좋다.
<stack 구조> 스택으로 관리될 레지스터를 가리킬 포인터가 필요하다.
그 호출한 함수에서 호출된 함수에 관한 레지스터
-------------------------------------------------------
main에서 호출한 함수에 관한 레지스터
--------------------------------------------------------
main에 관한 레지스터
Procedure Call Instructions
- Procedure Call : Branch and link 분기하고 돌아와야하기 때문에 link
BL ProcedureAddress(뛰어야 될 타겟 주소)
- Address of following instruction put in lr 링크레지스터 lr에 주소 집어넣고,
- Jumps to target address 분기 한다.
- Procedure return
MOV pc, lr 프로그램 카운터에 lr 값을 돌려놓으면 끝.
- Copies lr to program counter
- Can also be used for computed jumps
Leaf Procedure Example 하나 호출하고 여기서 끝.
C code
int leaf_example(int g, h, i, j){
int f;
f = (g+h) - (i+j);
return f;
}
- Arguments g, -- j in r0, -- r3
- f in r4(hence, need to save r4 on stack) r4를 저장해 논 다음에 쓸 수 있을 것이다.
- Result in r0
ARM code
SUB sp, sp, #12 12 즉 3칸 만든다. ( 한 word는 4바이트 ) 3개의 word
STR r6, [sp, #8] 스택 포인터로부터 8번째 떨어져있는 r6 저장.
STR r5, [sp, #4] 스택 포인터로부터 4번째 떨어져있는 r5 저장.
STR r4, [sp, #0] 스택 포인터 그위치에 r4를 집어 넣었다. 이따 쓸려고
ADD r5, r0, r1
ADD r6, r2, r3 r4,5,6 내맘대로 쓴다.
SUB r4, r5, r6
MOV r0, r4 r4값을 r0에 리턴.
LDR r4, [sp,#0] 수행 다 했으므로 r4,5,6을 원래대로 복원
LDR r5, [sp,#4]
LDR r6, [sp,#8]
ADD sp, sp, #12 스택포인터 위치를 원래대로 돌려넣는다.
MOV pc, lr 프로그램 카운터에다가 링크 레지스터 값 대입 Return.
Non Leaf Procedure
- Procedures that call other procedures
- caller needs to save on the stack : return address, any arguments and temporaries needed afeter the call
- Restore from the stack after the call
Non Leaf Procedure Example
C code
int fact( int n) {
if (n<=1) return f;
else return n*fact(n-1);
}
- Argument n in register r0
- Result in register r0
ARM code
fact :
SUB sp,sp,#8 // 2개의 stack을 만든다.
STR lr, [sp,#8] // return address 저장.
STR r0,[sp,#0] // r0에있는 argument n 저장.
CMP r0,#1 // n과 1을 비교.
BG L1 // 크면 분기.
MOV r0,#1 // result is 1
ADD sp,sp,#8 // 스택포인터 위치를 원래대로 돌려넣는다.
MOV pc,lr
L1 :
SUB r0,r0,#1 // n에 1빼고
BL fact // 다시 fact호출한다. 재귀
MOV r12,r0
LDR r0,[sp,#0]
ADD sp,sp,#8
MUL r0,r0,r32
MOV pc,lr
'Computer Architecture > 컴퓨터 구조' 카테고리의 다른 글
[14] CH2 명령어:컴퓨터 언어 < MIPS 버전 6 > (0) | 2022.01.19 |
---|---|
[13] CH2 명령어:컴퓨터 언어 < MIPS 버전 5 > (0) | 2022.01.19 |
[11] CH2 명령어:컴퓨터 언어 < MIPS 버전 4 > (0) | 2022.01.19 |
[10] CH2 명령어:컴퓨터 언어 < MIPS 버전 3 > (0) | 2022.01.19 |
[9] CH2 명령어:컴퓨터 언어 < MIPS 버전 2 > (0) | 2022.01.16 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!