아래 글 먼저 했다는 가정 하에 arm 어셈블리어 분석해보겠음.
[Linux BSP] Ubuntu에서 RaspberryPi U-Boot 코드 환경 분석
3dw 3칸 삭제하겠다 . 아까전에 했던 명령어 다시 실행하겠다. ubuntu@ubuntu8:~/pi_bsp/u-boot$ vi build.sh make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all ubuntu@ubuntu8:~/pi_bsp/u-boot$ chmod u+x build.sh ubuntu@ubuntu8:~/pi_bsp/u-b
program-developers-story.tistory.com
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 |