출처1 : http://downrg.com/417
출처2 : http://achiven.tistory.com/entry/%EC%A3%BC%EC%9A%94-ARM-%EC%96%B4%EC%85%88%EB%B8%94%EB%A6%AC-%EB%AA%85%EB%A0%B9
출처3 : http://egloos.zum.com/recipes/v/4986854
■ ARM Register와 Context
ARM Core를 잘 이해하기 위해서는 ARM Core에 내장되어 있는 기본 Register들이 어떻게 구성되어 있고, 사용되는지를 잘 알면 상당히 편리 하거든요. Register들은 Core가 사용할 수 있는 저장 매체 중에서 가장 빠른 속도를 자랑하며, ARM의 동작은 모두 아래의 Register들을 어떻게 장난 칠 것이냐가 그 실체이자 정체 인 거죠.
ARM core는 아래의 Register file을 가지고 있고요. 상당히 복잡해 보이지만, 별거 아닙니다. ARM core는동작 mode가 바뀌면 사용하는 Register set도 바뀝니다. 그림과 같이 7개의 동작 mode에 대하여 레지스터 set이 따로 존재하게 되며, ARM core는 32 bit register를 한 mode당 R0~R15까지 16개하고, CPSR + SPSR까지 더해서 18개씩 가지며, 총 7개 mode가 있으니까, 18 registers X 7개 mode = 126개의 Register를 가집니다....아아아아아아... 일줄 알았겠습니다만, 그러면 얼마나 좋으련만 아~ 틀렸습니다.
ARM core는 총 37개의 register를 가지고요. 왜냐! 삼각형이 그려진 register들을 banked register라고 부르며 그것들만이 각 mode별로 따로 있고요 나머지는 mode마다 모두 공용으로 사용합니다.

그러니까, 총
R0~R15 (16개) + CPSR (1개) + FIQ의 R8~R14, SPSR (8개) + SVC의 R13, R14, SPSR (3개)
+ Abort의 R13, R14, SPSR (3개) + IRQ의 R13, R14, SPSR (3개), UND의 R13, R14, SPSR (3개)
= 16 + 1 + 8 + 3 + 3 + 3 + 3= 37개 입니다.
이걸 실제 물리적으로 보면 이렇겠죠.. 으흐흐 구멍 숭숭 시원하겠네요.

뭐 여하간 mode가 바뀌면 쓰이는 Register가 바뀐다는 사실만 알면 됩니다. ㅋㅋ
뭐 예를 들면 다음처럼 들 수 있겠네요.
SVC mode로 돌다가 Fast Interrupt가 걸려서 FIQ mode로 진입했을 경우의 Register상태는

인 게지요. 우후후~ 뭐 괜찮아 보여요?
정리하면, 모든 mode가 공유하는 Register는 CPSR, PC, R0~R7까지는 모두가 공유합니다. 다른 말로는 CPSR, PC, R0~R7까지는 ARM core안에 한 개씩 밖에 없다~ 이거지요.
또 특이한 사항 하나는, System mode와 User mode는 완전히 똑같은 register set을 쓴다는 거에요. R0~R15, CPSR을 모두 같이 쓰며 딱 하나의 차이는 CPSR mode bits의 값만이 차이가 납니다. 여기서 주목할 점은 왜 System mode는 SPSR이 없느냐 하는 문제인데, 잘 생각해 보세요. 계속 즐겨볼 Exception에 그 해답이 있습니다.
이렇게 얘기 하다 보니, CPSR이라는 Register의 정체가 큰 역할을 하는 모양인데, 이 녀석의 정체를 살펴 봐야 하겠사옵니다. 도대체 CPSR, CPSR하는데 도대체 이놈은 뭐 하는 넘 이냐. CPSR은 특별한 Register 입니다. 특별한 용도의 Register들은 CPSR, SPSR, R15 (PC), R14 (LR), R13 (SP)가 있어요. 뭐, 그것들을 하나 하나 뜯어 먹어 보면...
CPSR은 약자를 풀어 놓으면 Current Program Status Register가 그 정체이고요. 그 모양새는

이에요.
32bit register이고요. 앞에 NZCV는 Flag field라고 해서, 뭔가 연산한 후에 set되는 register입니다.
이 field는 방금 처리된 연산 결과의 상태를 나타내요.
1) N : Negative : 연산결과가 마이너스인 경우에 set됩니다.
2) Z : Zero : 연산결과가 0인 경우에 set되요.
3) C : Carry : 연산결과에 자리 올림이 발생한 경우에 set 됩니다.
4) V : oVer flow : 연산의 결과가 overflow 났을 경우에 set되는데, Over flow라는건 넘치는 경우니까
원래 가져야 하는 Range보다 결과 값이 큰 경우가 그 경우에 해당됩니다.
이것의 필요성은 ARM의 철학이기도 한데, ARM Assembly section에서 또 다루기는 하겠지만,
ARM core는 Opcode를 Memory에서 가져오자 마자 (Fetch) 이를 무조건 실행하는 것이 아니라
condition flag인 NZCV를 보고 바로 앞 opcode의 실행결과를 보고 실행할지 말지를
결정할 수 있어요. Default는 AL "Always" , condition과 관게없이 항상 실행 이긴 하지만요.
뒤쪽에 IF는 IRQ나 FIQ가 걸릴 수 있는지에 관련한 field로서, 7번째 bit는 IRQ, 6번째 bit는 FIQ
Enable/ Disable을 나타내는 fiied입니다. 1로 set하면 Disable, 0으로 set하면 enable이죠.
이걸로 Interrupt가 걸리지 않도록 control가능합니다.
5번째 T 는 Thumb mode이냐, ARM mode이냐를 나타내는 field로서, ARM/ Thumb mode는
ARM Thumb mode section에서 자세히 다루니까 너무 급하게 생각 안하셔도 되요.
0~4의 5개 bit는 현재의 mode를 나타내는데,
현재 SVC인지, UND 인지, ABT 인지등을 나타냅니다. 이 register가 바로 현재 CPU의 상태
를 나타나겠죠. 아~주 중요한 register입니다.
그러니까, CPSR의 값은 현재의 mode도 확인 가능한 register 인거죠.
실은 CPSR의 하위 5bit를 원하는 mode로 setting하면 그 mode로 전환도 됩니다.
System mode와 User mode는 이 CPSR의 mode bit만 차이가 나고 나머지 Register는
모두 같이 사용합니다. 마치 부부처럼 한 몸입니다. *^^* 부끄.
여기서, SPSR은 또 뭐냐, Saved Program Status Register입니다.
SPSR은 말 그대로 CPSR을 복사해 넣는 특수 Register이지요. 그럼 언제 써먹느냐? CPSR을
backup 할 때 써먹지요. 그럼 언제 backup하느냐? SPSR에 CPSR의 값을 backup해 놓고
mode를 바꾸게 되었을 때, SPSR의 값을 CPSR에 다시 집어 넣으면 이전 mode로
곧바로 복귀할 수 있다는 것이지요!
R14 (Linked Register)는 또 뭐냐. 별거 아닙니다요. ARM은 어딘가로 branch (jump)를 할 때
어디서 branch 해 왔는지를 표시해 둡니다. 헨젤과 그래텔처럼 빵가루를 흘려두는 용도로 사용하는
거에요. 그렇게 하면 함수 같은거 불렀을 때 나중에 어디로 돌아가야 할지 LR만 보면 돌아 갈 수 있겠죠?
으흐흐.
R13 (Stack Pointer)는 현재 Stack을 어디까지 쌓아 두었는지를 가르킵니다.
이 이야그는 나중에 Stack에 대한 소고하고요, 함수의 구조 뭐 이런데서 더 자세히 폭로할 예정인데,
어쨌거나, Stack Pointer가 있으므로 해서 많은 것들이 가능하게 된거죠.
R15 (Program counter) 이 녀석은 현재 어디를 수행하고 있는 건지를 나타내는 거에요.
확장 to the CPU에서도 보았겠지만, 현재 Instruction을 Fetch해 온 위치를 가리키고 있어요. 요거 중요한 사실이니까 잘 기억해 두세요. 실행하는 위치가 아니라 Fetch해온 위치를 가리키는 거다~ 그거죠.
나머지 R0~R12까지는 CPU의 동작중의 저장용도로 적절히 사용되는 거지요. 그래서 R0~R12까지는 적당히 Register라고 부르고, R13~R15, CPSR, SPSR은 특별한 용도가 있다고 하여, Special Purpose Register라고 까지 구분해요. 췟.
Register 얘기를 꺼내고 나니, Context라는 거에 대해서 정의를 내리고 가야겠습니다. 이 Context라는 게 상당히 중요한 얘기거든요. Context를 문맥이라고들 많이 들 번역해 놓았는데, 너무 어렵죠. 저는 Context라는 말을 처음 접했을 때 도대체 이게 무신 소린가 했는데 이제서야 참으로 적당하고 철학적인 말이구나 하고 무릎을 탁 칠 때도 있긴 하거든요. Context Switching을 문맥전환 이라는 둥 해서 표현해 놓았는데, 너무 어렵더란 말이죠.
그래서 제가 고심한 끝에 더 쉬운 말은 없을까~ 해서 이렇게 표현을 하고 삽니다. "상황"
Context라는 건 MCU의 현재 상황, Context Switching이라는 건 상황을 바꿔 침. 뭐 그런 거죠. 그럼 그 상황이라는 건 뭐냐.
중대장 : 그 쪽 상황은 어때?
이등병 : 현재 김병장님은 야식 먹고 똥 싸러 가셨고, 저는 보초를 잘 서고 있습니다. 이상 무.
중대장 : OK 알겠다.
이렇듯이 모든 것을 종합한 상태를 말하죠. 그럼 이런 Software에서의 상황은 뭐냐?
바로 Register Set의 Snap Shot입니다. 그러니까 R0~R15, CPSR의 값들이 현재 상황이죠. 어느 순간에 찰칵 하고 Register에 들어 있는 값들을 사진 찍는 거에요. 이 값들만 있으면 현재 MCU가 뭘 하려고 했었는지, 뭘 하고 있었는지, 뭘 했는지 등등을 다 파악할 수 있습니다.
이 말은~ 다른 일을 하더라도 특정순간에 저장했던 Context를 다시 복원만 해줄 수 있다면 그 특정순간으로 돌아갈 수 있다~ 는 말입니다. 그 상황을 재현한다고도 말할 수 있겠죠.
결국엔 아래 Register 한 줄이 Context라고 보믄 됩니다. 어느 순간이든 아래의 Register set을 이용해서 MCU가 동작하고 있겠죠?

<나는 context>
완전 그림이 재탕 삼탕 이네요. ㅋㅋ.
요놈의 Context라는 개념을 알고 있으면 어느 Processor에나 들이댈 수 있습니다.
왜? 어느 Processor건 간에 어느 순간에건 이런 Register set을 이용해서 뭔가 하고 있으니까요.
R8~R12는 왜 색깔이 다른가요?
뒤에 나오겠지만 ARM, Thumb mode의 차이가 그 답입니다. Thumb mode는 R0~R7만 쓰고 ARM mode는 R0~R12까지 모두 씁니다. (R13, R14는 ARM/ Thumb에 상관없이 모두 쓰여요)
왜 FIQ는 banked register가 남들보다 많을까요?
그것이 mode가 있는 이유 중에 하나 입죠. 여러 가지 용도의 다른 mode로의 전환 시에 굳이 stack에 register backup을 하나라도 덜하면 시간 절약이 되겠습니다. 그런 이유에서 FAST!!! IRQ mode로의 전환은 더욱 빠르게 되어야 하니까, 전용 register를 하나라도 더 둔거죠.
■ ARM 어셈블리어 명령어 정리
※ 용어 정의
Rd: Destination Register / Rn: Operand1 Register / Rm: Operand2 Register
<cond>: Execution Condition code
<S>: S-Suffix - Status Update Suffix - SPSR의 값을 CPSR로 불러와서 Status를 Update
<!> : ! - Suffix - Writeback Suffix - [,]내의 선처리 연산 수행 후 값을 갱신
<Operand2>: Operand2가 가질 수 있는 형식
ㄱ. #Immediate: 32bit 명령에서 Immediate값은 8-bit pattern의 짝수 shift 값 만을 허용
ㄴ. Rm{, shift연산 #immediate}: Register(Rm)값에 #immediate 값으로 Shift 연산
§ Shift 연산의 종류
- asr(Arithmetic Shift Right): Immediate의 값 만큼 right shift, 앞에 bit는 Sign Extension
- lsr(Logical Shift Right): Immediate의 값 만큼 right shift, 앞에 bit는 0으로 채움
- lsl(Logical Shift Left): Immediate의 값 만큼 left shift, 뒤에 bit는 0으로 채움
- ror(ROtate Right): Immediate의 값 만큼 rotate right, rotate후 bit 0값은 carry에 저장
- rrx(Rotate Right eXtend): rrx는 1bit 씩 rotate right, bit 0값은 carry에 저장
1. 데이터 처리 명령(General Data Processing Instruction)
1.1 산술 연산
Syntax: add<cond><S> Rd, Rn, <Operand2>
add: Rd := Rn + <Operand2>
sub: Rd := Rn - <Operand2>
adc(ADd with Carry), sbc(SuBtract with Carry): Carry를 포함한 add, sub 연산
rsb(Reverse SuBtract): Rd := <Operand2> - Rn
rsc(Reverse Subract with Carry): Carry를 포함한 역 sub 연산
1.2 논리 연산
Syntax: and<cond><S> Rd, Rn, <Operand2>
and: Rd := Rn & <Operand2>
orr: Rd := Rn | <Operand2>
eor: Rd := Rn ^ <Operand2>
bic: Rd := Rn & !<Operand2>
1.3 Register 값 저장
Syntax: mov<cond><S> Rd, <Operand2>
mov: Rd := <Operand2>
mvn: Rd := !<Operand2>
1.4 비교
Syntax: cmp<cond><S> Rn, <Operand2>
cmp: Rn값에서 Opeand2값을 빼서 그 결과를 Status flag에 반영, SUBS와 동일한 명령
cmn: Rn값에서 Operand2값을 더해서 그 결과를 Status flag에 반영, ADDS와 동일한 명령
tst: Rn과 Opearand2를 bit and 연산을 수행해서 그 결과를 Status flag에 반영, ANDS와 동일한 명령
teq: Rn과 Operand2를 bit xor 연산을 수행해서 그 결과를 Status flag에 반영, EORS와 동일한 명령
2. 메모리 접근 명령(Memory Accesss Instruction)
Syntax: ldr<cond><B> Rd, label
ldr<cond><B><T> Rd, [Rn]
ldr<cond><B> Rd, [Rn, FlexOffset]<!> ;Pre-Indexed<Auto-Indexing>
ldr<cond><B><T> Rd, [Rn], FlexOffset ;Post-Indexed
<B>: B Suffix가 있을 경우 8-bit Unsigned byte 단위로 Access, 없을 경우 32-bit word로 Access
<T>: T suffix가 있을 경우 Processor가 User mode에서 memory access 처리
FlexOffset:
ㄱ.#Immediate: -4095 부터 -4096사이의 상수 값
ㄴ.{-}Rm{, shift연산}: Rm은 음의 부호를 가질 수 있으며, Rm의 Shift 연산도 가능함
2.1 Load 또는 Store 명령 예제
ldr r0, [r1]: r1에 저장된 주소를 이용해서 메모리로부터 r0로 값을 불러옴
str r0, [r1], #4: r0의 값을 메모리의 r1의 주소에 저장하고 r1을 +4함.
참고) 부호가 있는 Halfword, Byte로 읽을 때는 SH(Signed Halfword), SB(Signed Byte) <--(ldr only)
Unsigned Halfword로 읽거나 저장할 때는 H를 사용.
Doubleword의 경우 D 를 사용, 이 때의 Offset은 {-}Rm 만 허용함.
2.2 Multiple Load 또는 Store 명령
Syntax: ldm<cond><addrmode> Rn<!>, {reglist}<^>
<addrmode>: address mode에는 총 8가지가 있으며, 4가지는 address의 연상 방식에 따른
구분이며 4가지는 stack의 특성에 따른 구분이다.
- IA(Increment Address after each transfer), - IB(Increment Address after each transfer)
- DA(Decrement Address after each transfer), - DB(Decrement Address after each transfer)
- FD(Full descending stack): stack의 주소에 data가 저장이 된 상태이고, 주소가 감소하면서 저장
- ED(Emtpy descending stack): stack의 주소에 data가 없는 상태이고, 주소가 감소하면서 저장
- FA(Full ascending stack): stack의 주소에 data가 저장이 된 상태이고, 주소가 증가하면서 저장
- EA(Emtpy ascending stack): stack의 주소에 data가 없는 상태이고, 주소가 증가하면서 저장
<!>: ! - Suffix가 있을 경우 마지막 주소(최종으로 이동한 주소)를 Rn에 저장함
<^>: SPSR의 값을 CPSR에 넣어줌, S-Suffix와 동일한 기능을 수행함.
ldm: Rn으로 부터 reglist에 지정한 register 수 만큼 값을 불러옴
stm: reglist에 있는 register의 값들을 Rn에 저장함.
[주의] Reglist에 지정한 Register의 순서와 상관없이 Register의 번호가 낮은 값이
메모리의 낮은 주소에 저장 또는 읽어진다. reglist는 'r1,r2,r3' 또는 'r1-r3'으로 표현
[자주 사용되는 형식] STMFD sp!, {r4-r7,lr} / LDMFD sp!, {r4-r7,pc}
3. 분기 명령(Branch Instruction)
Syntax: b<cond> label
b: label이 있는 주소로 branch(PC값에 label의 주소를 입력)
bl: 다음 명령의 주소를 lr에 저장하고, b와 같이 label의 주소로 branch
4. 기타 명령어
4.1 Software Interrupt
Syntax: swi<cond> Immediate_24bit
swi: 지정한 번호를 갖는 Software Interrupt를 발생시킴, 해당 번호에 맞는 SWI vector로 branch
(Software Interrupt가 걸리면 프로세서의 모드는 Supervisor로 변경됨)
4.2 PSR Access
Syntax: mrs<cond> Rd, psr
psr에 지정한 값(cpsr 또는 spsr)로 부터 값을 불러와서 Rd에 저장 (Register <- PSR)
Syntax: msr<cond> psr_(field), #Immediate_8bit
msr<cond> psr_fields, Rm
Register(Rm)의 값 또는 8bit Immediate값을 psr(cpsr 또는 spsr)에 저장 (Register -> PSR)
(field): f, s, x, c 값이 선택적으로 올 수 있음. 지정한 field 영역에만 값을 저장함.
[주의] 프로세서가 User 또는 System mode일 때는 SPSR에 엑세스 하지 말아야 한다.
[자주 사용되는 형식] msr CPSR_c,r0
5. 상태 플래그와 실행 조건 코드(Status Flags & Execution Condition Codes)
N: 연산 결과가 음의 값을 가질 때 Set '1'
Z: 연산 결과가 영일 때 Set '1'
C: 연산 결과가 캐리(Carry)를 가질 때 Set '1'
V: 연산 결과 오버플로우(Overflow)를 발생시킬 때 Se

<ARM Instructioin Set>

① opcode<cond><S> Rd, Rn, #Immediate
② opcode<cond><S> Rd, Rn, Rm OP #Imm
③ opcode<cond><S> Rd, Rn, Rm OP Rs
- cmp, cmn 명령에서는 Rd는 무조건 '0' 값을 넣어줘야 함.(SBZ(Should Be Zero))
④ opcode<cond> Rd, Rn, #Immediate
⑤ opcode<cond> Rd, Rn, Rm OP #Imm
⑥ opcode<cond> Rd, <address>
⑦ opcode<cond><addrmode> Rm, Register_List^
⑧ opcode<cond><addrmode> Rm<!>, Register_List
⑨ opcode<cond><addrmode> Rm<!>, Register_List^
- P='1' Pre, P='0' Post / U='1' Increment, U='0' Decrement / B='1' Byte load, B='0' Word load /
W='1' Write-back(Auto-Index) W='0' / L='1' opcode는 ldr, L= '0' str /
I='1' Addr_mode가 모두 Offset field I='0' 앞에 Addr_mode는 '0' 뒤에 Addr_mode는 Rm /
S='1' Signed, S='0' Unsigned / H='1' Half Word, H='0' Word or Byte
⑩ b<cond> #Target Address(24bit Offset) - L의 값이 '1'이면 bl 명령
⑪ SWI #SWI Number
⑫ mrs<cond><S> Rd, PSR
⑬ msr<cond><S> PSR_<Field_Mask>, Rm
⑭ msr<cond><S> PSR_f, #Immediate
- S의 값이 '1'이면 SPSR에서, '0'이면 CPSR.
- SBO(Should Be One) 영역은 '1'로, SBZ(Should Be Zero) 영역은 '0'의 값을 넣어줘야 함.
■ 자주 사용되는 ARM 어셈블리 명령어 요약
1. MOV
ARM 어셈블리 명령어는 MOV 명령어와 논리 및 사칙연산 명령어에 모두 쉬프트 연산이
가능한데, 이것을 나타내는 표지가 끝에 붙을 수 있다는 것에 유의한다.
쉬프트 연산에는 ASR(오른쪽 쉬프트, 빈자리는 부호가 따라옴),
LSR(오른쪽으로 쉬프트, 빈자리는 0으로 채워짐),
LSL(왼쪽으로 쉬프트, 빈자리는 0으로 채워짐),
ROR(오른쪽으로 rotation )
정도를 알아두면 유용하다.
예)
MOV r0, [r2,r4] ; r2+r4 의 주소에 있는 값을 읽어서 r0에 저장한다.
MOV r1, r2, ROR #1 ; r2를 오른쪽으로 한 비트만큼 rotation 해서 r1에 저장
2. ADD, SUB, AND, ORR
예)
ADD r1, r2, #4 ; r2에 4를 더해서 r1에 저장
SUB r1, r1, #1 ; r1의 값을 하나 감소
ORR r4, r5, r7, LSR r2 ; r7을 오른쪽으로 논리 쉬프트를 r2만큼 한다음 그 결과를
; r5와 or 연산하여 r4에 저장한다.
3. UMULL, SMULL
곱하기 연산이다. 32비트짜리 두 개를 곱하면 64비트짜리가 나오므로 결과값을 저장하는
데 두 개의 레지스터가 필요하다. 결과 레지스터의 위치에 주의한다. UMULL은 부호가
없는 곱하기이고, SMULL은 부호가 있는 곱하기 이다.
예)
UMULL r4, r5, r1, r2 ; r1과 r2를 곱해서 상위 32비트는 r5에 저장하고 하위 32비트는
; r4에 저장한다.
5. B, BL, BNE, BEQ, CMP
BL은 분기 명령이다.
예)
B there ; 라벨이 there인 곳으로 무조건 분기한다.
BL sub+ROM ; 계산된 위치의 서브루틴을 호출한다.
BNE(0이 아닌 경우 분기)와 BEQ(0이면 분기) 는 branch 명령어이고 CMP는 비교 명령
어이지만 둘이 같이 쓰이는 경우가 많으므로 한꺼번에 설명한다.
예)
CMP r1, #4 ; r1이 4이면 플래그가 0으로 셋팅된다.
BEQ there ; 플래그가 0이면 라벨이 there인 곳으로 분기하고, 그렇지 않으면
; 다음 명령어가 수행된다.
6. LDR, STR
LDR은 load 명령이다. LDR에는 불러오는 변수의 크기에 따라 LDRB, LDRH, LDR의 세
가지 종류가 있다. LDRB는 byte 변수를 불러올 때, LDRH는 short 변수를 불러올 때,
LDR은 int 변수를 불어올 때 쓴다. STR는 store 명령으로 마찬가지로 STRB, STRH, STR
이 있다.
첫 번째 인자는 레지스터가 두번 째 인자는 주소가 된다. 세 번째 인자는 load/store 연
산을 한 다음 주소값을 증가시키고자 할 때, 얼마만큼 증가시킬 지를 지정한다.
예)
LDR r1, [r2, #16] ; r2에 16 byte만큼 더한 주소에서 정수형 값을 읽어와 r1에 저장한다.
STR r1, [r2], #4 ; r2의 주소에 r1을 저장하고 난 후, r2를 4만큼 증가시킨다.
7. LDMFD, STMFD
LDM/STM은 LDR/STR의 변종으로 블록 단위로 load/store 할 때 사용한다. 중요한 용도
는 스택에 레지스터 값을 저장하거나 복원하는 것이다. 왜냐하면 스택에 저장/복원할 때
는 여러 개의 레지스터를 저장/복원해야 하기 때문이다.
스택과 관련해서는 LDMFD/STMFD, LDMED/STMED, LDMFA/STMFA, LDMEA/STMEA 등
이 사용되고, 스택과 관련없이 사용할 때는 LDMIA,LDMIB, LDMDA, LDMDB, STMIA,
STMIB, STMDA,STMDB 가 사용된다.
중요한 것은 스택과 관련해서 실제 사용할 때, 쌍으로 사용한다는 것이다.
LDMFD/STMFD 정도만 잘 사용하면 된다. 자세한 사항은 ADS 문서를 참고하기 바란다.
예)
STMFD sp!, {r4-r6, lr} ; 스택에 r4-r6와 lr 레지스터를 저장하고 sp를 그만큼 감소시킨다.
LDMFD sp!, {r4-r6, pc} ; 스택에서 r4-r6와 pc를 복원하고 sp를 그만큼 증가시킨다.
ARM Developer Suite(ADS) 1.2 에서 C 코드와 ASM 코드 섞어 쓰기
1. C 코드 내에 어셈블리 코드를 inline으로 사용하기
(1) 사용방식
asm("instruction[;instruction]");
또는 C 컴파일러의 구문을 사용하면 다음과 같다.
__asm
{
instruction [; instruction]
...
[instruction]