---------------------------------------------------------------------- ARM7 강좌 [10] : Instruction Set(4) ---------------------------------------------------------------------- 오늘 강좌에서는 Data Processing Instruction에 대해서 계속 이어나가도록 하겠습니다. 되도록이면 오늘 이부분을 다 커버하고 싶습니다만 해봐야 겠 지요. 지난 강좌에서 다루었던 내용중 오퍼랜드쪽 부분은 계속 겹치는 내용 이므로 의문이 생기시면 이전 강좌로 돌아가서 확인해 보시길 바랍니다. 1) MVN{cond}{S} Rd,Op2 해당 명령은 Rd:=NOT Operand2 의 의미를 가진 명령입니다. 기존 어셈블 러에서는 볼 수 없었던 낯설은 명령이네요. 기능은 써 있듯이 MOV처럼 값을 넣기는 넣는데 NOT를 해서 넣는 명령입니다. 이런 명령이 왜 있는 지에 대해서는 확실히 모르긴 몰라도, 아마도 ARM7에서 8비트Resolution Immediate 오퍼랜드만 다룰 수 있기 때문인 듯 합니다. 해당 명령으로 어느정도 기능을 확장한다고 할까요? 바로 예제로 들어가겠습니다. Ex1) MVN r0,#0 ; r0 := -1 : 사실 MVN의 용도로 위의 경우 밖에는 사용된걸 보지 못했습니다. 만약 MOV r0,#0xFFFFFFFF 이렇게 하면 에러가 발생합니다. 이것 은 누누히 설명드리지만 ARM7의 모든 명령이 32비트 한 워드이고 Immediate 오퍼랜드처리를 8비트 값을 Rotate시키는 방식으로 사 용하기 때문인데, MVN을 사용함으로서 해당 값을 넣을 수 있습니 다. 다른 부분은 MOV와 동일하므로 그다지 이슈가 될 것이 없을 듯 하군요. 2) ADD{cond}{S} Rd, Rn, Op2 ADC{cond}{S} Rd, Rn, Op2 더하기 명령입니다. 8086과 큰 차이는 오퍼랜드를 3개 지정한다는 것입 니다. Rd는 결과가 저장될 레지스터로, Data Processing 명령 모두는 그 결과가 레지스터(Rd)로 들어가야만 합니다. 첫번째 Rd가 결과가 저장 될 레지스터이고, 나머지 두개가 서로 더해질 오퍼랜드입니다. 두개의 오퍼 랜드 중 하나는 또 항상 레지스터여야만 합니다. Op2는 거듭 말씀드리지 만 Shifted Register 혹은 Rotated Immediate Value 중 하나입니다. ADD와 ADC는 널리 사용되는 대로 더하기, 더하는데 캐리플래그랑 같이 더하기... 정도입니다. Ex1) ADD r0,r0,#1 ; r0:=r0+1 Ex2) ADD r0,r1,r2 ; r0:=r1+r2 Ex3) ADDS r0,r1,r1, LSL #2 ; r0:=r1*5 : 위의 명령을 보면 ARM 명령어의 강력함을 알 수 있죠? 위 에서 Rd는 r0, Rn은 r1, Op2 부분이 r1,LSL #2 입니다. r1값 더하기 r1을 두번 쉬프트 한 값, 즉 r1*4값이므로 결과적으로는 *5가 되 겠지요... S 옵션이 사용되었으므로 플래그 레지스터에 영향을 미칩니다. 그러면? 위의 1번 2번 예제는 수행하더라도 플래그 레 지스터는 영향을 안받는다는 의미지요.. 사용하기에 따라서 강력 한 역할을 할 수 있을듯 합니다. Ex4) in C int addints(int a,int b) { int c; c=a+b; return c; } in ARM7 Assembly ADD r0,r0,r1 ; r0:=r0+r1 MOV pc,lr ; return 사실 인수 전달에 관련된 코드가 더 들어가겠지만, 코어부분은 대 강 위와 같습니다. 3) SUB{cond}{S} Rd, Rn, Op2 SBC{cond}{S} Rd, Rn, Op2 RSB{cond}{S} Rd, Rn, Op2 RSC{cond}{S} Rd, Rn, Op2 위의 네 명령은 빼기 명령입니다. SUB와SBC는 그런대로 알만 한데... R로 시작하는 두개가 더 있네요. R은 감수(?) 와 피감수를 바꾸는 역할 을 합니다. 즉, SUB 명령이 Rd=Rn-Op2 라면 RSC는 Rd=Op2-Rn 입니다. 이런 명령이 왜 필요할 까요? 글세요... 우선 Op2가 Rn에 비해서 상대 적으로 유연성이 좀더 많아서일까요? 어떻든... 개념은 어렵지 않습니 다. SBC와 RSC는 캐리플래그가 관련되어 있는 명령입니다. 그런데 명령 해 석을 보면 다음과 같이 나와 있네요. SBC Rd, Rn, Op2 = Rd=Rn-Op2+Carry-1 아마도 8086에서의 캐리와는 좀 다른 모양입니다. 뺄셈을 했을 때 자리 내림이 발생을 하면 캐리가 클리어 되는 구조이군요. 아마도 2의 보수 연산을 하기 때문인듯 합니다. 즉 1을 빼고 싶은 경우 1의 2의 보수를 취해 더해주죠. 해당 값은 FFFFFFFF 이고, 대상이 0이 아니라면 더하기 를 통해 캐리가 발생하겠군요. 근데 원래 하고자 했던것이 뺄셈이었으 니까... 피감수가 0인 경우에 캐리가 발생하지 않았고, 나머지의 경우 에는 모두 캐리가 발생합니다. 기계적 사고방식에는 그게 맞나 봅니다. 어떻든 중요한건 뺄셈 연산을 통해 borrow가 발생한다면 Carry는 0이고 발생하지 않는다면 Carry는 1이 되는 것이죠. 따라서 SBC와 같은 명령 에서는 Carry를 오히려 더해주고 다시 1을 빼 줌으로써 8086 등에서 사 용되는것과 동일한 효과를 얻게 되는군요. Ex) 64Bit 뺄셈 SUBS r4,r0,r2 SBC r5,r1,r3 : 이렇게 하면 [r5:r4]=[r1:r0]-[r3:r2] 가 되겠군요. {S}옵션에 주의하시길 바랍니다. 4) AND{cond}{S} Rd, Rn, Op2 EOR{cond}{S} Rd, Rn, Op2 ORR{cond}{S} Rd,Rn, Op2 : 이번에는 Bit연산에 관련된 명령어들입니다. AND는 그대로 AND,EOR은 XOR쯤으로, ORR은 OR로 생각하시면 됩니다. B 명령을 제외하고는 웬 만한 명령어는 모두 3글자인데, 그래서 ORR로 표기하는 듯합니다. 역 시 오퍼랜드는 같은 의미입니다. Ex1) AND r0,r0,#0xFF : r0의 8비트만 남기는 명령입니다. Ex2) ANDCSS r0,r1,r2,ASR r3 : 만약 캐리 플래그가 설정되어 있다면...(CS) r1 AND (r2>>r3) 정 도를 하는데, 해당 명령의 결과가 플래그 레지스터에 영향을 미 칩니다. ASR과 LSR의 차이는 ASR의 경우 최 상위 비트가 1이라면 해당 비트는 계속 1로 유지를 하는 것이죠.LSR이라면 새로 들어 오는 비트는 항상 0입니다. 이것은 음수를 2의 보수로 사용하는 시스템에서 필요한 방법입니다. 참 결과는 r0에 넣는군요. Ex3) EORS r0,r0,r0 : 해당 명령을 수행하면 r0는 0이 될 것이고, N 플래그도 0이 되고 Z플래그는 1이 됩니다. Ex4) MOV r0,#0xFF ORR r0,r0,#0xFF00 : r0에 0xFFFF를 넣는 방법입니다. 5) BIC{cond}{S} Rd, Rn, Op2 : Rd := Rn AND (NOT Op2) 로 설명이 되어 있는 명령입니다. 별별 명령 이 다 있다는 생각이 드는군요. AND하기전에 NOT을 한번 해서 처리하 는 명령입니다. 의미는 비트를 클리어하는 것이구요, Op2에 지정한 비트가 0으로 지워지는 결과가 나타납니다. Ex) BIC r0,r1,#3 : r0 := r1 and 0xFFFFFFFC 의 의미입니다. 6) CMP{cond} Rn, Op2 CMN{cond} Rn, Op2 : 비교 명령입니다. MOV, MVN처럼 인수가 2개인데요, 이번에는 Rd가 빠 졌습니다. CMP는 흔히 보던 그 CMP입니다. Rn에서 Op2를 빼 보는 명 령이죠. 아시다시피 레지스터값에는 영향을 미치지 않고 플래그 에만 영향을 미칩니다. 그러고보니 {S}옵션도 없네요... 이 명령들은 디폴 트로 {S}를 준 효과가 나타납니다. (일설에는 어셈블러가 그렇게 해 준다고 그러던데, 기계어 코드로는 S 옵션을 꺼놓은 CMP도 가능하지 않을까 싶네요..) CMN은 좀 새롭군요. 이 명령은 CMP가 빼기를 하는데 반해, 두 오퍼랜 드를 더해 보는 명령입니다. 역시 생소한 개념인데요... 그럴필요도 있을까요? 어떻든 CMP가 빼기를 해보는 거라면 CMN은 더하기를 해 보 는 명령어랍니다. Ex1) CMP r2,#23 MOVEQ r2,#45 : 만약 r2가 23이라면 45를 넣어라... Ex2) CMP r0,#0 CMPEQ r1,#0 CMPEQ r2,#0 CMPEQ r3,#0 MOVEQ r4,#12 : r0부터 r3까지 모두 0이라면 r4에 12를 넣는 명령입니다. 참 재 미 있는 구조라고 생각됩니다. Ex3) CMN r1,r2 MOVEQ r0,#0 MVNNE r0,#1 : r0 = ((r1+r2)==0) ? 0:-1; 위에서 조건부 명령의 강력함을 느낄 수 있으신가요? 아니라면 다음을 한번 보시죠... in C while (a!=b) { if (a>b) a-=b; else b-=a; } in ASM with no conditional Instruction gcd CMP a,b JZ end JNZ less_than SUB a,a,b JMP gcd less_than SUB b,b,a JMP gcd end ... * ARM도 아니고 8086도 아니고... 명령어가 이상하게 되었네요.. 대충 의미만 파악하시길.. in ARM7 gcd CMP a,b SUBGT a,a,b SUBLT b,b,a BNE gcd .... 직접 보시고.. 소감을... 7) TEQ{cond} Rn, Op2 TST{cond} Rn, Op2 : CMP와 거의 비슷한 구조를 갖는 명령입니다. 기능도 거의 유사합니다. CMP가 -, CMN이 + 라면, TEQ는 XOR, TST는 AND 연산을 통해 같은 일 을 합니다. 하지만 특징이라면 Logical 연산이 일어날 경우 플래그중 에서 V 플래그(오버플로우 플래그)는 영향을 받지 않습니다. 이걸 잘 응용하면 다음과 같은 처리가 가능합니다. Ex1) CMP r0,#31 ; test r0<=31 ? TEQ r0,#127 ; test r0==127 ? MOVLS r0,#'.' ; if either then r0='.' Ex2) TST r1,#3 ; is r1 word aligned? MOVEQ r0,#1 ; r0:=1 if so MOVNE r0,#0 ; else r0:=0 지난번에 다루었던 MOV 명령까지를 합치면 총 16개의 명령을 설명드렸습니 다. 이로서 가장 비중이 큰(분량이 많은?) Data Processing 명령의 설명을 마쳤군요. 참고로 다루고 있는,혹은 앞으로 다룰 명령의 종류는 다음과 같습니다. (1) Branch 명령 (2) Data Processing 명령 (3) PSR Transfer 명령 (4) Multiply 명령 (5) Single Data Transfer 명령 (6) Block Data Transfer 명령 (7) Swap 명령 (8) SWI 명령 이밖에도 코프로세서 관련 명령이 있기는 하지만... 그정도까지는 좀 무리 인 듯 싶습니다. 위에 써 놓은 것을 보니 무척 많아 보이는데요, 막상 살펴보면 분류당 1개 -2개 정도 의 명령밖에는 없습니다. 자.. 그럼 오늘 강좌는 여기에서 줄이겠습니다.
Hacked Brain/embeddedland.net