본문 바로가기

Hacked Brain/embeddedland.net

ARM7 강좌 [10] : Instruction Set(4) (출처 : 디지털 동호회)

----------------------------------------------------------------------
               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개 정도 의 명령밖에는 없습니다.

자.. 그럼 오늘 강좌는 여기에서 줄이겠습니다.