Bare‐metal‐C‐Ch03‐빌드과정과‐GNU툴체인 - Hongjayeong-02/Basic_SoC_implementation GitHub Wiki

Ch03. 빌드 과정과 GNU 툴체인

(Bare-metal-C-00-필수개념) 00번 페이지 6절에서 요약한 빌드 파이프라인(전처리→컴파일→어셈블→링킹)을 이 챕터에서 arm-none-eabi-* 도구를 직접 손으로 호출해서 눈으로 확인한다. IDE가 "Build" 버튼 뒤에서 숨기는 과정을 직접 지휘해보는 것.

1. 이론

1.1 왜 단계를 알아야 하는가

IDE에서 "Build" 한 번으로 끝나는 작업이 사실은 다섯 단계로 나뉘어진다는 걸 알면, 링커/링커스크립트 관련 에러(예: "undefined reference", "region overflowed")를 만났을 때 어느 단계에서 문제가 생기는지 바로 감이 온다.

1.2 단계별 요약

단계 입력 출력 도구 하는 일
전처리 main.c main.i gcc -E #include, #define 치환
컴파일 main.i main.s gcc -S C → ARM 어셈블리
어셈블 main.s main.o gcc -c (내부적으로 as) 어셈블리 → 목적코드(ELF, 미링크)
링킹 *.o *.elf gcc + 링커스크립트 여러 .o를 하나로 합치고 주소 배치
로케이팅 *.elf .hex/.bin objcopy 플래시에 그대로 구울 이미지 추출

1.3 외워둘 포인트

  • 전처리기는 C 문법을 모른다. 단순 문자열 치환기라서 #define REG (*(volatile ...)0x40020400) 같은 매크로도 그대로 복사-붙여넣기만 한다.
  • .elf와 .hex/.bin은 용도가 다르다. .elf는 디버깅 심볼(함수명, 줄번호 대응 등)까지 포함한 "풀" 파일이고, .hex/.bin은 그 중 순수 메모리 내용만 뽑은, 플래시에 그대로 구울 수 있는 이미지다.

2. 코드 (main.c — Ch02와 동일)

Ch02의 main.c를 그대로 쓰면서, 이번엔 Makefile 대신 스크립트(build.sh)로 단계를 하나씩 직접 호출한다:

arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=soft -E main.c -o main.i
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=soft -S main.i -o main.s
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=soft -c main.s -o main.o
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=soft -T linker.ld main.o startup.o -o ch03_build.elf
arm-none-eabi-objcopy -O ihex ch03_build.elf ch03_build.hex

3. 코드 설명

3.1 -mcpu=cortex-m4와 FPU 옵션

-mcpu=cortex-m4는 F411/F439 공통(둘 다 Cortex-M4F 코어). 다만 F439ZI는 하드웨어 FPU(FPv4-SP)를 갖고 있으므로, 부동소수점을 쓰는 챕터(Ch06 이후)부터는 -mfloat-abi=hard -mfpu=fpv4-sp-d16로 전환한다. 지금은 정수 레지스터 조작만 하므로 -mfloat-abi=soft로 충분하다.

3.2 objdump로 역어셈블 확인

arm-none-eabi-objdump -d main.o

이 명령으로 main.o 안의 기계어를 다시 어셈블로 "역"변환해서 볼 수 있다. 예를 들어 delay()의 while(count--) 루프가 subs(빼기) / cmp(비교) / bne.n(같지 않으면 분기) 수준의 어셈블로 컴파일되는 것을 직접 확인할 수 있다 — C의 "제어문"이 실제로는 어떤 저수준 명령어로 바뀌는지 보는 가장 직관적인 방법.

4. 실습 결과

  • ch03_build.elf 크기: text 252 / data 0 / bss 0 — Ch02의 Makefile 빌드 결과와 정확히 동일 (같은 소스, 같은 링커스크립트이므로 당연한 결과).
  • 이 "동일함" 자체가 검증의 핵심 — Make로 하든 손으로 명령을 치든, 같은 소스/옵션이면 같은 바이너리가 나온다는 걸 직접 확인한 것.

5. 시험 대비 핵심 정리

  • Q. 빌드 단계 순서는? → 전처리 → 컴파일 → 어셈블 → 링킹 → 로케이팅
  • Q. .i, .s, .o, .elf는 각각 어느 단계의 산출물? → 전처리(.i) → 컴파일(.s) → 어셈블(.o) → 링킹(.elf)
  • Q. .elf와 .hex의 차이는? → .elf는 디버깅 심볼 포함한 "풀" 파일, .hex/.bin은 플래시용 순수 메모리 이미지
  • Q. F439ZI에서 -mfloat-abi=hard를 쓸 수 있는 이유는? → F439ZI는 하드웨어 FPU(FPv4-SP)를 내장

네비게이션: 이전: Bare-metal-C-Ch02-레지스터-직접정의 · Bare‐metal-C-Programming · 다음: Bare-metal-C-Ch04-링커스크립트와-스타트업

⚠️ **GitHub.com Fallback** ⚠️