임베디드 개발(before)/IoT 임베디드 SW 개발자 양성과정

[28일차] ARM 프로세서 이해 및 활용(ARM 프로세서의 명령어)

주운녕 2020. 8. 20. 15:09

◎ 32비트 ARM 명령어

▷ 모든 ARM 명령은 32비트로 구성되어 있다.

- Load/Store와 같은 메모리 참조 명령이나 Branch 명령에서는 모두 상대주소(Indirect Address)방식을 사용한다.

- Immediate 상수는 32비트 명령어 내에 표시된다. (32비트 내에 상수 + 기타 상태 명령 등)

▷ 모든 ARM 명령어는 조건부 실행이 가능하다.

▷ Load/Store Architecture를 사용한다.

 

◎ 16비트 Thumb 명령어 (16비트 데이터라인이 추세이던 시절 32비트 ARM이 호환하기 위해 만든 명령어)

▷ 32비트의 ARM 명령을 16비트로 재구성한 명령

▷ 조건부 실행 불가능, 상수값의 표현 범위가 적다.

 

◎ Java 명령

- 유닉스 위에 윈도우 위에 자바VM 을 올려야 사용할 수 있다. 디버깅이 어려운 단점이 있다.

 

● 32비트 ARM 명령어

명령어 요약
32비트 arm 명령어 구조

▷ 조건부 실행

- ARM에서 모든 명령을 조건에 따라 실행 여부 결정 가능.

- Branch 명령의 사용을 줄인다.

:: Branch 명령이 사용되면 pipeline이 stall(멈춤)되고 새로운 명령을 읽어오는 사이클의 낭비가 따른다.

- Condition Field

:: 모든 명령어는 condition field를 가지고 있으며 cpu가 명령의 실행 여부를 결정하는 데 사용된다. 

:: Current Program Status Register(CPSR)의 Condition flag의 값을 사용하여 조건을 검사한다.

▷ 조건부 실행 방법

- 조건에 따라 명령어를 실행하도록 하기위해서는 적절한 조건을 접미사로 붙여주면 된다.

조건 필드 : condition 비트의 상태를 보고 조건부 실행을 한다.

▷ Branch 명령어

- BL [address] :: r14(LR)에 PC값을 저장한다.

- Bx [레지스터(r0)]

▷ Branch 명령어의 구성

- 분기할 주소 계산

:: PC값을 기준으로 비트[23:0]에 해당하는 Offset이 사용.

- 24비트의 Offset

:: 맨 상위 비트는 +/- sign 비트

:: 나머지 23비트를 이용하여 2비트 왼쪽으로 shift 한 값을 사용

:: 분기 가능한 어드레스 영역 : PC +/- 32MB 

▷ Branch with Link(BL)명령

- 다음에 수행할 명령의 위치를 LR(Link Register)에 저장한다.

- LR = PC - 4

:: PC : 실행되는 위치(x), Fetch가 되고 있는 위치(o)

:: 실제 pipeline을 따라보면 현제 Fetch 되고 있는 명령어의(즉 현재 PC의) 두 단계 이전의 명령어가 execute(실행) 되고 있다.

● Data Processing 명령어 실습

▷ main함수 - 어셈블러 함수로 되어있는 부분에 접근한다.

void Main(void)
{
	Uart_Init(115200);
	Uart_Printf("\nHello ARM Processor!!!\n\n");
	
	/* 
	 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
	 *   FROM HERE WE WILL TEST ARM INSTRUCTION
	 */

#if 0
	/* Testing how to return */
	Uart_Send_String("Start How-to-return test\n");
    HOW_TO_RETURN();
    Uart_Send_String("Success\n");
#endif

#if 0
	/* Testing conditional execution */
{
	/* 
	 * GET A RESULT
	 *    if (a < b) result = 1;
	 *    else if (a > b) result = 2
	 *    else if (a == b) result 3
	 */
	int a,b, result;
	
	a=9;b=11; /* a < b condition */
	Uart_Printf("Compare %d and %d => ", a, b);
    result = CONDITIONAL_EXECUTE(a,b);
    Uart_Printf("Result : %d (must 1)\n",result);
    
	a=11;b=10; /* a > b condition */
	Uart_Printf("Compare %d and %d => ", a, b);
    result = CONDITIONAL_EXECUTE(a,b);
    Uart_Printf("Result : %d (must 2)\n",result);
    
	a=10;b=10; /* a == b condition */
	Uart_Printf("Compare %d and %d => ", a, b);
    result = CONDITIONAL_EXECUTE(a,b);
    Uart_Printf("Result : %d (must 3)\n",result);        
}
#endif


#if 0
	/* IMPLEMENT the function for calcurate result=(a+b)-c */
{
	int a,b,c;
	int result;
	
	a = 11;
	b = 22;
	c = 30;
	
	Uart_Printf("Calcurate [(%d+%d)-%d] ",a,b,c);
	result = DATA_PROCESS1(a,b,c);
	Uart_Printf("=> Result is %d (must 3)\n",result);	
}
#endif

#if 0
	/* IMPLEMENT the function for calcurate result=(a<<2) | (b&15) */
{
	unsigned long a,b;
	unsigned long result;
	
	a = 0x10;
	b = 0x33;
	/*
	 * unsigned long function(a,b)
	 */
	Uart_Printf("Calcurate [(0x%08x << 2) | (0x%08x & 15)] \n",a,b);	
	result = DATA_PROCESS2(a,b);
	Uart_Printf("   => Result is 0x%08x (must 0x00000043)\n",result);	
}
#endif

#if 0
	/* Sum of Decimal Test */
{
	int start, end, sum;
	start = 1;
	end = 100;

	Uart_Printf("Start sum of decimal test\n");
	
	sum = SUM_OF_DEC(start,end);
	Uart_Printf("ASM : Sum from %d to %d is [%d]\n",start,end,sum);

	sum = 0;
	for (start=1;start<=end;start++) {
		sum += start;
	}
	Uart_Printf("C   : Sum from %d to %d is [%d]\n",1,end,sum);
}
#endif

	
#if 0
	/* Testing MES Test */
{
	
	int a=30;
	int b=18;
	int mes;
	Uart_Printf("\n*** Test GCD ***\n");
	mes = GCD(a,b);
	Uart_Printf("MES = %d \n", mes); 
}
#endif 

▷ libs.S 어셈블 파일 -> 어셈블리어로 되어있다.

/*
 * =====================================================================
 * The Function for Testing
 * =====================================================================
 */
 
	/* 
	 * void HOW_TO_RETURN(void);
	 * -----------------------------------------------------------------
	 */
	.globl  HOW_TO_RETURN
HOW_TO_RETURN:
	/* IMPLEMENT HERE : return ? */	
	BX	lr
	/* IGNORE this branch instruction */
	b	.
 

 	/* 
	 * int CONDITIONAL_EXECUTE(int a, int b);
	 * -----------------------------------------------------------------
	 *    r0=a, r1=b
	 *    The return value is result (r0)
	 */
	.globl  CONDITIONAL_EXECUTE
CONDITIONAL_EXECUTE:
	/* IMPLEMENT HERE
	 * use CMP and MOV instruction only : 4 line
	 * result must be stored to r0 as follow ATPCS
	 */
	
	CMP r0, r1
	movlt r0, #1
	movgt r0, #2
	moveq r0, #3
	 
 	mov pc, lr	/* return */
 	
	/* 
	 * int DATA_PROCESS1(int a, int b, int c);
	 * -----------------------------------------------------------------
	 *    r0=a, r1=b, r2=c
	 *    The return value is result (r0)
	 */
	 .globl	DATA_PROCESS1
DATA_PROCESS1:
	/*
	 * IMPLEMENT function for calcurate result=(a+b)- c in this location
	 * use R3 Destination Register(Rd)
	 * use ADD, SUB and MOV instruction : 3 line
	 */

	ADD r3, r0, r1
	SUB r0, r3, r2
	
	 mov pc, lr	/* return */

	/* 
	 * unsigned long DATA_PROCESS2(unsigned long a, unsigned long b);
	 * -----------------------------------------------------------------
	 *    r0=a, r1=b
	 *    The return value is result (r0)
	 */
	 .globl	DATA_PROCESS2
DATA_PROCESS2:	 
	/*
	 * IMPLEMENT function for calcurate result=(a<<2) | (b&15) in this location
	 * use R2 Destination Register(Rd)
	 * use AND, ORR and MOV instruction : 3 line
	 */
	
	and r2, r1, #15
	orr r2, r2, r0, lsl #2
	mov r0, r2
	 
	 mov pc, lr	/* return */	
 
	/* 
	 * int SUM_OF_DEC(int start, int end);
	 * -----------------------------------------------------------------
	 *    r0=start, r1=end
	 *    The return value is SUM (r0)
	 */
	.globl  SUM_OF_DEC
SUM_OF_DEC:
	/* IMPLEMENT HERE  */
	
mov r2, #0

LABEL_A:

add r2, r0
add r0, #1

cmp	r1, r0 /* 1씩 증가하는 r0와 end값인 r1을 비교 */

BGE	LABEL_A /*조건부 실행 : r1이 r0과 같거나 크면 LABE_A로 Branch */

mov r0, r2

	mov pc, lr	/* return */
	
	/* 
	 * void GCD(int a, int b); 최대 공약수
	 * -----------------------------------------------------------------
	 * 	r0=30, r1=18 r1을 항상 작은 값으로
	 * 	The return value is MES
	 */
	.globl GCD	
GCD:
	/* IMPLEMENT HERE :  */
	
label_b:
	
	mov r2, r1
	SUB r1, r0, r1
	mov r0, r2
	cmp	r0, r1
bgt	label_b

	mov r0, r1
	
	mov pc, lr 	 	/* return */

▷ 결과

 


* 개인적인 학습 목적으로 작성한 글이기에 내용에 잘못된 정보가 있을 수 있습니다.