그라운드 임베디드 유튜브 구독

노트

기계어와 어셈블리 노트

하드폴트가 났을 때, 최적화가 코드를 바꿨을 때, 결국 봐야 하는 건 기계어입니다.

로드맵에서 보기 →
GROUND EMBEDDED · 정리 노트기계어 01명령어 한 줄의 정체 1C: x = x + 1; 2어셈블리: adds r3, r3, #1 3기계어: 0x1C5B
기계어와 어셈블리

명령어 한 줄의 정체

기계어는 CPU가 읽는 숫자이고, 어셈블리는 그 숫자에 붙인 이름입니다. C 한 줄이 몇 개의 숫자가 되는지 봅니다.

GROUND EMBEDDED · 정리 노트기계어 02Thumb 명령어 읽기 1ldr r3, =0x40020014 ; GPIOA_ODR 주소 2ldr r2, [r3] ; 현재 값 읽기 3orr r2, r2, #0x20 ; 5번 비트 켜기 4str r2, [r3] ; 다시 쓰기
기계어와 어셈블리

Thumb 명령어 읽기

Cortex-M이 쓰는 Thumb 명령어 집합에서 자주 나오는 MOV, LDR, STR, B, BL을 실제 디스어셈블 예로 읽어 봅니다.

GROUND EMBEDDED · 정리 노트기계어 03레지스터와 호출 규약레지스터역할r0~r3인자 전달, 반환값(r0), 함수 안에…r4~r11함수가 쓰려면 저장했다가 복원해야 함
기계어와 어셈블리

레지스터와 호출 규약

인자는 r0~r3, 반환값은 r0, 돌아갈 주소는 lr, 스택 위치는 sp. 함수 경계에서 레지스터가 어떻게 쓰이는지 정한 약속.

GROUND EMBEDDED · 정리 노트기계어 04C와 어셈블리 대조 1arm-none-eabi-objdump -d -S firmware.el…
기계어와 어셈블리

C와 어셈블리 대조: 최적화 옵션이 바꾸는 것

간단한 C 함수를 디스어셈블해서 한 줄씩 맞춰 보고, -O0과 -O2가 같은 코드를 얼마나 다르게 만드는지 비교합니다.

GROUND EMBEDDED · 정리 노트기계어 05스타트업 코드01리셋 순서02Reset_Handler가하는 일03실무에서만나는 문제
기계어와 어셈블리

스타트업 코드: main 전에 일어나는 일

리셋 직후 CPU는 .data를 RAM으로 복사하고 .bss를 0으로 채운 뒤에야 main을 부릅니다. startup.s를 한 줄씩 따라갑니다.

GROUND EMBEDDED · 정리 노트기계어 06링커 스크립트와 섹션 1MEMORY { 2 FLASH (rx) : ORIGIN = 0x08000000, LE… 3 RAM (rwx) : ORIGIN = 0x20000000, LE… 4}
기계어와 어셈블리

링커 스크립트와 섹션

.text, .rodata, .data, .bss가 Flash와 RAM의 어디에 놓이는지 정하는 파일. 맵 파일과 함께 읽는 법.

GROUND EMBEDDED · 정리 노트기계어 07벡터 테이블 1void TIM2_IRQHandler(void) { ... }// 이름이…
기계어와 어셈블리

벡터 테이블: 인터럽트 주소록

초기 스택 값과 리셋, 예외, 인터럽트 처리 함수의 주소가 차례로 놓인 표. 부트로더가 이 표를 옮기는 이유까지.

GROUND EMBEDDED · 정리 노트기계어 08하드폴트 분석 1void HardFault_Handler(void) { 2 __asm volatile ("tst lr, #4\n ite e… 3} 4void hf_c(uint32_t *sp) {
기계어와 어셈블리

하드폴트 분석: 어느 줄에서 죽었나

하드폴트가 나면 스택에 저장된 PC와 LR, 그리고 폴트 상태 레지스터로 원인과 위치를 찾습니다.