본문 바로가기
Firmware Programming

[ARM] ARM 어셈블리어 분석

by TYB 2024. 2. 13.
반응형

아래 글 먼저 했다는 가정 하에 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.S에 추가되어 잇는 어셈블리어 코드가 컴파일 되면서 arm에 맞는 어셈블리어로 바뀐거임.

 

그러면 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 구조로 가는거임.

 

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로 함으로써 훨씬 큰 범위의 값을 사용가능함.)

 

손으로 정리하면 아래와 같다.

 

 

 

 

 

start.S

명령어 뒤에 S 접미사를 삽입하면 조건 플래그가 변경(상태 레지스터 업데이트)되는거임. 연산 결과를 상위

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형