[17호]JK전자와 함께하는 ARM 완전정복(3)-2
JK전자와 함/께/하/는 ARM 완전 정복 Ⅱ.ARM Applications – 1부글 | JK전자 |
2. 어셈블리어 실습
2.1 ARM Simulator 환경 설정
IAR ARM용 컴파일러는 가격이 그렇게 싸지는 않습니다. 다행히도 www.iar.com 에서 시간 제한(30일), 사이즈 제한(32Kbyte) 버젼을 다운 받아서 사용해 볼 수 있습니다.
2.1.1 IAR Evaluation 버젼 다운로드
- 다운로드 사이트 방문
http://supp.iar.com/Download/SW/?item=EWARM-EVAL
패키지 사이즈가 약 830MB정도 입니다. 다운 받아서 설치하시기 바랍니다.
다음은 Evaluation 버젼을 다운로드 받기 위한 절차대로 화면을 캡쳐해 놓은 것입니다. 참조하시기 바랍니다.
반드시 “Code size limited”를 선택하시기 바랍니다. 그렇지 않으면 30일 이후에 더이상 IAR 컴파일러를 사용할 수 없게 됩니다.
(2) IAR Evaluation 버젼 설치
설치가 완료되면 마지막에 License 를 입력하는 화면이 나옵니다. 여기에서 “Register with IAR System to get an evaluation license”를 선택하시기 바랍니다.
현재 설치된 제품 중에 라이센스가 없는 제품의 리스트가 나옵니다. 선택을 하고 “다음”으로 진행합니다.
IAR Evaluation 버젼을 다운받기 위해서 입력했던 Email 주소로 Registeration Confirm 메일이 와있을 것입니다.
Confirm 메일에 있는 Confirm 링크를 클릭하면 “Registration Complete”와 함께 Evaluation License 번호를 알 수가 있습니다. 그 번호를 위의 화면의 빈 칸에 입력하고 나서 “Regiser”버튼을 누르면 잠시 후에 네트워크를 통해서 Evaluation 라이센스 번호를 받게 됩니다. 경우에 따라서 Fail 이라는 메세지가 나올 수도 있습니다. 그때는 “Register”버튼을 다시 한번 클릭해서 재시도해 보시기 바랍니다.
모든 설치가 완료된 화면입니다.
2.1.2 ARM Simulator 프로젝트 생성
아래 화면대로 따라서 ARM Simulator 기반의 실습 프로젝트를 생성해 보시기 바랍니다.
(3) 프로젝트 파일이름 입력 – “arm_simulator”
(4) 그룹생성 – “base”, “testcode”그룹 생성
- “base”그룹 : 2440init_ewarm.s 추가
- “testcode”그룹 : main.c, SegInit.c 추가
(6.1) Target Device 설정
Samsung S3C2440A 로 설정합니다.
(7) Processor Mode 설정
“ARM”모드로 설정합니다.
(8) Scattor Loading 파일 설정
프로젝트 디렉토리에 “arm_simulator.icf”파일을 선택합니다.
(9) Program Start Entry 설정
“ __program_start”라고 입력합니다.
(12) Debugger 정보 설정 : Dirver – Simulator, Run to main은 반드시 설정 해제합니다.
2.2 Data Processing Instructions
2장에서는 ARM Simulator를 활용한 어셈블리어 실습을 해보도록 하겠습니다. 이 내용들은 ARM Architecture Instruction의 이론 부분을 설명할 때 한번씩 나왔던 내용입니다. 여기서는 이론으로 공부했던 내용들을 실제로 ARM Simulator에서 코드를 작성한 후 컴파일하고 실행해서 결과 값을 직접 확인해 보는데 의미가 있습니다.
R0 = 0×00 R1 = 0×22 R2 = 0×02 R3 = 0×00 R4 = 0×00 |
레지스터 값이 위와 같을 때 아래 예제들을 차례대로 수행해 보세요.
(1) AND R0, R0, #0xFF
2440init_ewarm.s 파일에 다음과 같이 입력을 합니다.
SECTION IMAGE_STARTUP:CODE (2) PUBLIC __program_start CODE32 __program_start b ResetHandler b HandlerUndef ;handler for Undefined mode b HandlerSWI ;handler for SWI interrupt b HandlerPabort ;handler for PAbort b HandlerDabort ;handler for DAbort b . ;reserved b HandlerIRQ ;handler for IRQ interrupt b HandlerFIQ ;handler for FIQ interrupt ResetHandler MOV R0, #0×00 MOV R1, #0×22 MOV R2, #0×02 MOV R3, #0×00 MOV R4, #0x00AND R0, R0, #0xFF ADD R0, R0, #1 ADD R0, R0, R1 LSL R1, R0, #2 SUB R3, R2, R1, LSR R2HandlerFIQ b .HandlerIRQ b .HandlerUndef b .HandlerSWI b .HandlerDabort b .HandlerPabort b .END |
(2) ADD R0, R0, #1 ; R0 = R0 + 1 = 0×1
- 실행 결과
(3) ADD R0, R0, R1 ; R0 = R0 + R1 = 0×01 + 0×22 = 0×23
- 실행 결과
(4) LSL R1, R0, #2 ; 0×23(100011) LSL #2 = 0x8C(10001100) -> 참고로 왼쪽으로 2번 쉬프트 하면 *4 를 한 것과 같습니다.
- 실행 결과
(5) SUB R3, R2, R1, LSR R2
- 실행 결과
R3의 값이 0xFFFFFFDF 로 복잡한 값이 나왔습니다. 왜 이런 결과가 나왔을까요? 우선 R1을 오른쪽으로 2번 쉬프트시키면 0×23이 되고 R2(0×02)에서 R1(0×23)을 빼면 결과 값이 -0×21가 되고 이 값을 2의 보수로 표시하면 0xFFFFFFDF가 됩니다.
0×21 = 00000000000000000000000000100001
-0×21 = 11111111111111111111111111011111 –> 0×21의 2의 보수
참고로 2의 보수를 취하는 방법은 원래의 2진수에서 0->1, 1->0 으로 바꾼 후에 1을 더하면 되겠지요.
2.3 Multiply Instructions
R0 = 0×01 R1 = 0×02 R2 = 0×03 R3 = 0×04 |
레지스터 값이 위와 같을 때 아래 예제들을 차례대로 수행해보세요.
(1) MUL R2, R0, R1 ; R2 = R0*R1 = 0×02
2440init_ewarm.s 파일에 다음과 같이 입력을 합니다.
ResetHandler MOV R0, 0×01 MOV R1, 0×02 MOV R2, 0×03 MOV R3, 0x04MUL R2, R0, R1 MULS R2, R0, R1 MLA R3, R2, R1, R0 |
(2) MULS R2, R0, R1 ; R2 = R0*R1 = 0×02
MUL 명령과 같은 명령입니다. 하지만 MUL뒤에 “S”가 붙으면 명령어 처리가 끝난 이후에 CPSR의 Flag Field가 연산 결과에 따라서 업데이트가 됩니다.
- 실행 결과
(3) MLA R3, R2, R1, R0 ; R3 = R2*R1 + R0
참 효율적이네요. 명령어 하나로 곱하기 연산과 더하기 연산을 같이 할 수 있습니다.
- 실행 결과
2.4 Load/Store Instructions
2.4.1 Pre-index
R0 = 0×31000000
R1 = 0×00
R2 = 0×00
(1) LDR R1, [R0] ; R1 2440init_ewarm.s 파일에 다음과 같이 입력을 합니다.
ResetHandler MOV R0, 0×31000000 MOV R1, 0×0 MOV R2, 0x0LDR R1, [R0] STR R1, [R0, #4] STR R1, [R0, #4]! |
(3) STR R1, [R0, #4]! ; R1
- 실행 결과
2.4.2 Post-index
R0 = 0×31000000
R1 = 0×00
R2 = 0×04
(1) LDR R1, [R0], R2 ; R1
ResetHandler MOV R0, 0×31000000 MOV R1, 0×0 MOV R2, 0x4LDR R1, [R0], R2 STR R1, [R0], #4 |
(2) STR R1, [R0], #4 ; R1
- 실행 결과
2.5 Load/Store Multiple Instructions
R0 = 0x000A
R4 = 0x000B
R5 = 0x000C
R13 = 0xFFF0
(1) STMIA R13!, {R0,R4-R5}
ResetHandler MOV R0, #0x000A MOV R4, #0X000B MOV R5, #0x000C LDR R13, =0xFFF0STMIA R13!, {R0,R4-R5} |
(2) STMIB R13!, {R0,R4-R5}
ResetHandler MOV R0, #0x000A MOV R4, #0X000B MOV R5, #0x000C LDR R13, =0xFFF0STMIB R13!, {R0,R4-R5} |
(3) STMDA R13!, {R0,R4-R5}
ResetHandler MOV R0, #0x000A MOV R4, #0X000B MOV R5, #0x000C LDR R13, =0xFFF0STMDA R13!, {R0,R4-R5} |
(4) STMDB R13!, {R0,R4-R5}
ResetHandler MOV R0, #0x000A MOV R4, #0X000B MOV R5, #0x000C LDR R13, =0xFFF0STMDB R13!, {R0,R4-R5} |
2.6 Branch Instructions
ResetHandlersubsequent MOV R0, #1 MOV R1, #2 BL func1 ADD R2, R0, R1func1 MOV R0, #3 MOV R1, #4 BL func2 ADD R2, R0, R1 MOV PC, LRfunc2 MOV R0, #5 MOV R1, #6 ADD R2, R0, R1 MOV PC, LR |
위의 예제를 실행하면 R2 레지스터에 “3”이 저장이 되지 않습니다. R2 레지스터에 “3”이 저장이 될 수 있도록 예제를 수정해 보시기 바랍니다. 수정한 예제 코드는 아래와 같습니다.
서브 함수를 호출 할 경우에는 서브 함수에서 사용하는 레지스터와 LR 레지스터를 반드시 저장한 이후에 사용해야 한다는 것을 알 수 있습니다.
2.7 Status Register Access Instructions
ResetHandler MRS R0, CPSR BIC R0, R0, #0×80 ; 7번 비트를 clear 하면 인터럽트가 활성화 됩니다. MSR CPSR, R0 |
2.8 Conditional Execution
지금까지 배운 모든 어셈블리어들을 활용해서 최종적으로 몇가지 예제를 풀어 보도록 하겠습니다. 예제를 구현하는데에는 여러가지 방법들이 많이 있겠지만 가장 최적화된 어셈블리 명령어를 사용하시기 바랍니다.
(1) 1 ~ 10을 더하는 최적화된 어셈블리어로 작성해 보세요.
ResetHandler MOV R5, #10 MOV R6, #0 loop_sum ADD R6, R6, R5 SUBS R5, R5, #1 BNE loop_sum ; Not Equal(Z=1) |
루프를 사용할 경우에는 거꾸로 도는 것이 효율적입니다.
(2) 2개 변수 사이의 절대값을 구하세요.
- [-2 - 3] 사이의 절대값
ResetHandler MOV R0, #-2 MOV R1, #3SUBS R0, R0, R1V RSBMI R0, R0, #0 |
“SUBS R0, R0, R1”명령을 실행했을 때의 그림입니다. R0, CPSR의 “N”Flag를 잘 살펴보시기 바랍니다. 참고로 RSBMI 명령어는 CPSR의 “N”Flag가 Set되어 있을 때 뺄셈을 하는데 SUB 명령과는 연산의 방향이 반대로 수행이 되는 명령어입니다. 그러니까 이번 예제에서는 “#0”에서 “R0”를 빼는 것입니다.
- [3 - 1] 사이의 절대값
ResetHandler MOV R0, #3 MOV R1, #1SUBS R0, R0, R1 RSBMI R0, R0, #0 |
“SUBS R0, R0, R1”명령을 실행했을 때의 그림입니다. R0, CPSR의 “N”Flag를 잘 살펴 보시기 바랍니다.
3장에서는 우리가 실제로 실습에 사용할 S3C2440 ARM9 개발보드에 대해서 소개하도록 하겠습니다. ARM Simulator에서는 별다른 설정없이도 어셈블리어 실습을 할 수 있었으나 실제 타겟을 사용할 경우에는 개발보드의 메모리 컨트롤러, 부팅과정 등을 제대로 이해하고 있어야 코드 작성이 가능합니다. 실제 개발보드에서 실습을 하기 전에 S3C2440에 대해서 이론적으로 공부해보도록 하겠습니다.
JK전자와 함께하는 ARM 완전정복(3)-2 에서 계속 됩니다.