아래 글 먼저 했다는 가정 하에 arm 어셈블리어 분석해보겠음.
start.S 파일은 소스 코드이고, start.o 파일은 이 소스 코드를 컴파일하여 생성된 오브젝트 파일임.
arm-linux-gnueabihf-objdump 명령을 사용하여 start.o 파일의 어셈블리 코드를 확인해서 해당 오브젝트 파일이 어떤 어셈블리 명령어로 이루어져 있는지 알아보자.
ubuntu@ubuntu8:~/pi_bsp/u-boot/arch/arm/cpu/armv7$ arm-linux-gnueabihf-objdump - S start.o
start.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <reset>:
.global switch_to_hypervisor_ret
#endif
reset:
/* Allow the board to save important registers */
b save_boot_params
0: eafffffe b 64 <save_boot_params>
00000004 <save_boot_params_ret>:
#ifdef CONFIG_ARMV7_LPAE
/*
* check for Hypervisor support
*/
mrc p15, 0, r0, c0, c1, 1 @ read ID_PFR1
4: ee100f31 mrc 15, 0, r0, cr0, cr1, {1}
and r0, r0, #CPUID_ARM_VIRT_MASK @ mask virtualization bits
8: e2000a0f and r0, r0, #61440 ; 0xf000
cmp r0, #(1 << CPUID_ARM_VIRT_SHIFT)
c: e3500a01 cmp r0, #4096 ; 0x1000
beq switch_to_hypervisor
10: 0afffffe beq 68 <switch_to_hypervisor>
00000014 <switch_to_hypervisor_ret>:
#endif
/*
* disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
* except if in HYP mode already
*/
mrs r0, cpsr
14: e10f0000 mrs r0, CPSR
and r1, r0, #0x1f @ mask mode bits
18: e200101f and r1, r0, #31
teq r1, #0x1a @ test for HYP mode
1c: e331001a teq r1, #26
bicne r0, r0, #0x1f @ clear all mode bits
20: 13c0001f bicne r0, r0, #31
orrne r0, r0, #0x13 @ set SVC mode
24: 13800013 orrne r0, r0, #19
orr r0, r0, #0xc0 @ disable FIQ and IRQ
28: e38000c0 orr r0, r0, #192 ; 0xc0
msr cpsr,r0
2c: e129f000 msr CPSR_fc, r0
#if !CONFIG_IS_ENABLED(SYS_NO_VECTOR_TABLE)
/*
* Setup vector:
*/
/* Set V=0 in CP15 SCTLR register - for VBAR to point to vector */
mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTLR Register
30: ee110f10 mrc 15, 0, r0, cr1, cr0, {0}
bic r0, #CR_V @ V = 0
34: e3c00a02 bic r0, r0, #8192 ; 0x2000
mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTLR Register
38: ee010f10 mcr 15, 0, r0, cr1, cr0, {0}
#ifdef CONFIG_HAS_VBAR
/* Set vector address in CP15 VBAR register */
ldr r0, =_start
3c: e59f00cc ldr r0, [pc, #204] ; 110 <delay+0x1c>
mcr p15, 0, r0, c12, c0, 0 @Set VBAR
40: ee0c0f10 mcr 15, 0, r0, cr12, cr0, {0}
#endif
/* the mask ROM code should have PLL and others stable */
#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT)
#ifdef CONFIG_CPU_V7A
bl cpu_init_cp15
44: ebfffffe bl 6c <cpu_init_cp15>
#endif
#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT_ONLY)
bl cpu_init_crit
48: ebfffffe bl cc <cpu_init_crit>
#endif
#endif
bl kcci_led_test
4c: ebfffffe bl d0 <kcci_led_test>
bl _main
50: ebfffffe bl 0 <_main>
00000054 <c_runtime_cpu_setup>:
ENTRY(c_runtime_cpu_setup)
/*
* If I-cache is enabled invalidate it
*/
#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
54: ee070f15 mcr 15, 0, r0, cr7, cr5, {0}
dsb
58: f57ff04f dsb sy
isb
5c: f57ff06f isb sy
#endif
bx lr
60: e12fff1e bx lr
00000064 <save_boot_params>:
* Stack pointer is not yet initialized at this moment
* Don't save anything to stack even if compiled with -O0
*
*************************************************************************/
WEAK(save_boot_params)
b save_boot_params_ret @ back to my caller
64: eafffffe b 4 <save_boot_params_ret>
00000068 <switch_to_hypervisor>:
ENDPROC(save_boot_params)
#ifdef CONFIG_ARMV7_LPAE
WEAK(switch_to_hypervisor)
b switch_to_hypervisor_ret
68: eafffffe b 14 <switch_to_hypervisor_ret>
0000006c <cpu_init_cp15>:
#endif
/*
* Invalidate L1 I/D
*/
mov r0, #0 @ set up for MCR
6c: e3a00000 mov r0, #0
mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
70: ee080f17 mcr 15, 0, r0, cr8, cr7, {0}
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
74: ee070f15 mcr 15, 0, r0, cr7, cr5, {0}
mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array
78: ee070fd5 mcr 15, 0, r0, cr7, cr5, {6}
dsb
7c: f57ff04f dsb sy
isb
80: f57ff06f isb sy
/*
* disable MMU stuff and caches
*/
mrc p15, 0, r0, c1, c0, 0
84: ee110f10 mrc 15, 0, r0, cr1, cr0, {0}
bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
88: e3c00a02 bic r0, r0, #8192 ; 0x2000
bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
8c: e3c00007 bic r0, r0, #7
orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
90: e3800002 orr r0, r0, #2
orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
94: e3800b02 orr r0, r0, #2048 ; 0x800
#if CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache
#else
orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache
98: e3800a01 orr r0, r0, #4096 ; 0x1000
#endif
mcr p15, 0, r0, c1, c0, 0
9c: ee010f10 mcr 15, 0, r0, cr1, cr0, {0}
mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register
orr r0, r0, #1 << 22 @ set bit #22
mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register
#endif
mov r5, lr @ Store my Caller
a0: e1a0500e mov r5, lr
mrc p15, 0, r1, c0, c0, 0 @ r1 has Read Main ID Register (MIDR)
a4: ee101f10 mrc 15, 0, r1, cr0, cr0, {0}
mov r3, r1, lsr #20 @ get variant field
a8: e1a03a21 lsr r3, r1, #20
and r3, r3, #0xf @ r3 has CPU variant
ac: e203300f and r3, r3, #15
and r4, r1, #0xf @ r4 has CPU revision
b0: e201400f and r4, r1, #15
mov r2, r3, lsl #4 @ shift variant field for combined value
b4: e1a02203 lsl r2, r3, #4
orr r2, r4, r2 @ r2 has combined CPU variant + revision
b8: e1842002 orr r2, r4, r2
/* Early stack for ERRATA that needs into call C code */
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
ldr r0, =(CONFIG_SPL_STACK)
#else
ldr r0, =(SYS_INIT_SP_ADDR)
bc: e59f0050 ldr r0, [pc, #80] ; 114 <delay+0x20>
#endif
bic r0, r0, #7 /* 8-byte alignment for ABI compliance */
c0: e3c00007 bic r0, r0, #7
mov sp, r0
c4: e1a0d000 mov sp, r0
mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register
orr r0, r0, #1 << 12 @ set bit #12
mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register
#endif
mov pc, r5 @ back to my caller
c8: e1a0f005 mov pc, r5
000000cc <cpu_init_crit>:
* Jump to board specific initialization...
* The Mask ROM will have already initialized
* basic memory. Go here to bump up clock rate and handle
* wake up conditions.
*/
b lowlevel_init @ go setup pll,mux,memory
cc: eafffffe b 0 <lowlevel_init>
000000d0 <kcci_led_test>:
.word __rel_dyn_start - pie_fixup
_rel_dyn_end_ofs:
.word __rel_dyn_end - pie_fixup
#endif
ENTRY(kcci_led_test)
ldr r0,=0xFE200000
d0: e59f0040 ldr r0, [pc, #64] ; 118 <delay+0x24>
ldr r1,=0x09240000
d4: e59f1040 ldr r1, [pc, #64] ; 11c <delay+0x28>
str r1,[r0,#0x00]
d8: e5801000 str r1, [r0]
ldr r1,=0x00012249
dc: e59f103c ldr r1, [pc, #60] ; 120 <delay+0x2c>
str r1,[r0,#0x04]
e0: e5801004 str r1, [r0, #4]
ldr r1,=0x00000040
e4: e3a01040 mov r1, #64 ; 0x40
mov r2, #8
e8: e3a02008 mov r2, #8
000000ec <ledloop>:
ledloop:
str r1, [r0,#0x1C]
ec: e580101c str r1, [r0, #28]
ldr r3,=0x400000
f0: e3a03501 mov r3, #4194304 ; 0x400000
000000f4 <delay>:
delay:
subs r3,r3, #1
f4: e2533001 subs r3, r3, #1
bne delay
f8: 1afffffd bne f4 <delay>
str r1,[r0,#0x28]
fc: e5801028 str r1, [r0, #40] ; 0x28
mov r1,r1,LSL #1
100: e1a01081 lsl r1, r1, #1
subs r2,r2,#1
104: e2522001 subs r2, r2, #1
bne ledloop
108: 1afffff7 bne ec <ledloop>
mov pc,lr
10c: e1a0f00e mov pc, lr
ldr r0, =_start
110: 00000000 .word 0x00000000
ldr r0, =(SYS_INIT_SP_ADDR)
114: 07fffee0 .word 0x07fffee0
ldr r0,=0xFE200000
118: fe200000 .word 0xfe200000
ldr r1,=0x09240000
11c: 09240000 .word 0x09240000
ldr r1,=0x00012249
120: 00012249 .word 0x00012249
너무 기니까 터미널에 안띄우고 파일로 만들어서 보자
ubuntu@ubuntu8:~/pi_bsp/u-boot/arch/arm/cpu/armv7$ arm-linux-gnueabihf-objdump -S start.o > start.txt
ubuntu@ubuntu8:~/pi_bsp/u-boot/arch/arm/cpu/armv7$ vi start.txt
start.txt 들어가서 보면
232 mov r2, #8
233 e8: e3a02008 mov r2, #8
윗 부분은 start.o의 내용인거고
그러면 start.o의 내용을 다시 뜯어서 살펴보자면
0x e 3 a 0 2 0 0 8
1110 0011 1010 0000 0010 0000 0000 1000
arm 명령어를 해석해보자.
최상위 4bit 1110[31:28]은 조건필드-> mov뒤에 접미사가 없으면 디폴트로 AL이 들어감.
그 다음 4bit 0001[27:] 살펴보면 Data Processing 구조로 가는거임.
1110 0011 1010 0000 0010 0000 0000 1000
arm 명령어를 들고와서 데이터 처리 명령어의 구조에 맞게 해석해보면
op2는 1 , opcode는 1010 / Set Conditioncode =0 /
source register는 없고
dst register는 2 즉, R2
op2[25번비트]가 1이었으므로 operand2(immediate 상수)는 0000 0010 1000 ( 12비트를 쓰는데, 그 중 4비트를 rotate bit로 함으로써 훨씬 큰 범위의 값을 사용가능함.)
손으로 정리하면 아래와 같다.
명령어 뒤에 S 접미사를 삽입하면 조건 플래그가 변경(상태 레지스터 업데이트)되는거임. 연산 결과를 상위
'Firmware Programming' 카테고리의 다른 글
[Ubuntu-RaspberryPi] C언어로 U-Boot gpio제어를 통한 led 동작 및 버튼 제어 (1) | 2024.02.14 |
---|---|
[ARM] ARM 프로세서 기초 (0) | 2024.02.13 |
[Firmware Programming] C++ ESP32-CAM 보드 UDP camera frame 패킷 순서 제어 및 실시간 전송 (2) | 2024.02.10 |
[Firmware Programming] ESP32-CAM 보드 UDP camera frame 패킷 순서 제어 및 실시간 전송 (1) | 2024.02.10 |
[Firmware Programming] ESP32-CAM 보드 usb로 upload 하기 (1) | 2024.02.08 |