View

300x250

첫 번째로, Input_data에서 연속한 주소를 둘 가져와 레지스터에 저장하는 코드를 작성하면 첫 주소를 R1에 불러오고, 그 값에 4 Byte를 더한 값을 R2에 저장. 이렇게 작성할 수 있겠다. 

ldr r0, =Input_data 

add r1, r0, #4


그 다음, R0이 가진 주소가 가리키는 Memory에 저장된 값을 R2, R1의 값을 R3에 저장한다.

ldr r2, [r0]

ldr r3, [r1]


이 코드를 실행하면 다음과 같은 레지스터 상태가 된다.


밑작업은 다 해줬다. 

이제, 값을 비교하고 조건에 따라 Swap하는 방법에 대한 Instruction들을 입력해주면 한 번의 Loop를 작성하게 된다.


값 비교는 CMP 라는 Instruction을 이용한다. 

CMP는 비교대상인 레지스터에 저장된 값을 바꾸는 Instruction은 아니지만, CPSR의 값들을 바꿔준다. 이 CPSR에 대해 좀 자세하게 찾아보았다.


CPSR : Current Program Status Register. 즉, 현재 프로그램의 상태를 나타내는 레지스터에 해당한다.

ARM CPU에는 18개의 레지스터가 있는데, (16개로 봐야할 지, 18개로 봐도 무방한지는 잘 모르겠다. )

R0 ~ R7의 8개의 레지스터는 범용 레지스터로, 말 그대로 빈 공간에 해당한다. 

R8 ~ R12의 5개의 레지스터는 FIQ모드를 가진다. FIQ모드는 Fast Interrupt Request 모드로, 입력장치나 네트워크 등에서 CPU의 작업 중간에 신호가 왔을 때 처리하기 위해 사용한다. 해당 모드에만 사용되는 레지스터 영역이기에 접근이 빠르다. 나머지 모드에서는 범용 레지스터로 사용된다.

R13은 SP (Stack Pointer) 라고도 불리는데, 이름 그대로 스택 메모리의 가장 윗부분을 가리킨다. 쌓이면 스택 포인터도 증가하고, 빼면 스택 포인터도 감소한다. 

R14는 LR (Link Register) 로 서브루틴, 예외 처리등으로 흐름에 변화가 생겼을 때, 종료 후 다시 돌아올 수 있도록 위치를 저장하는데 사용된다. 

R15는 PC (Program Counter) 로, 프로그램 명령어를 읽어올 위치를 나타내는 레지스터이다. 

CPSR은 Current Program State Register로, 현재 프로그램의 상태를 나타내는 레지스터이다.

SPSR은 Saved Program State Register로, 이전의 CPSR 값을 저장해놓는 레지스터이다. 


CPSR의 구조를 뜯어보면,

Condition Flag, Reserved, Extension, Control 4개로 나뉜다. 이 중에서 Condition Flag가 문제 해결과 연관이 있기에 각각의 역할을 살펴보자면 다음과 같다.

N - Negative Flag : 음수일때 1이 된다.

Z - Zero Flag : 0일때 1이 된다. 

C - Carry Flag : carry out과 같은 값. 

V - Overflow Flag : overflow가 일어나 sign bit이 틀리면 1이 된다. 

ARM Instruction 뒤에 S를 붙이면 명령 수행 후 CPSR Flag를 업데이트 한다는 의미로, 이를 통해 값을 바꿀 수 있다.

또한, Instruction 뒤에 조건 접미사들을 붙이면, If문처럼 작용하여 CPSR 값을 조건으로 하여 수행할지 말지를 결정하는데도 사용된다.


다시 문제상황으로 돌아와서, CMP Instruction에 대해 보자면, 

CMP R1, R2 

이 문장을 실행하면 R1, R2를 비교하여 ( R1에서 R2를 뺀 값이 양수이면 R1이 큰 거고, 음수이면 R1이 작은거고, 0이면 두 값이 같은 것 ) CPSR의 NZCV Flags 를 업데이트한다. ( 음수일때는 N Flag만 1이 되고, 0일때는 Z Flag와 C Flag 모두 1이 된다, CMP는 S 접미사를 붙여주지 않아도 알아서 작동한다! )

CPSR값을 조건으로 사용하기 위해서 Instruction 뒤에 Condition Field ( 조건 접미사들 ) 을 붙여줘야하는데, 다 소개하긴 힘들 것 같으니 필요한 사람은 "이곳"을 참조하세요.

내가 쓸 Condition Field는 N Flag가 1일 때 진행 : MI ( Minus ) / NV Flag가 같을 때 진행 : GE ( signed Greater or Equal ) 이다.


만약에 N Flag가 1이 되었다면 앞의 값이 뒤의 값보다 작다는 의미이므로 그대로 두고, ZC Flags가 1이 되었다면, 앞의 값이 뒤의 값보다 크다는 의미이므로 Swap해줘야한다.

Swap 함수의 구현은 단순하게 주소값에 서로의 값을 넣어주는 것으로 처리하려 한다.

STRGE R2, [R1]    : NV Flag가 같으면, R2의 값을 R1의 메모리주소가 가리키는 곳에 저장

STRGE R3, [R0]    : NV Flag가 같으면, R3의 값을 R0의 메모리주소가 가리키는 곳에 저장 



이렇게 코드를 작성할 수 있겠다.

디버깅을 위해 다음과 같이 Input을 약간 수정하여 앞의 수가 뒤의 수보다 작게 만들면

CPSR Condition Flags 가 다음처럼 0 - 2 의 결과인 -2에 의해 Negative Flag만 1이 되고

메모리상의 Data는 스왑되지 않고 그대로 남아있다.


반면, 원래 코드의 경우에는

비교 후 0과 2 두 값의 위치가 바뀌어있다. ( Swap )



이번 포스팅도 점점 길어지는 걸로 봐서 이쯤에서 끊고 다음 포스팅으로 올려야 할 듯 하다.

다음 글에서는 Loop를 넣는 방법에 대해 찾아보고, 작성하겠다.


320x100
Share Link
reply
반응형
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31