| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- FIFO 설계
- lec check
- Keynote 표
- keynote
- Cortex-M3
- ISR
- ARM
- BSS
- booth algorithm
- 곱셈기 설계
- ACK Polling
- keynote 도형 회전
- LinkedList
- Async FIFO
- booth multiplier
- i2c
- keynote 도형 복사
- keynote 사용법
- SPI mode
- c
- LEC
- 비동기 FIFO 구조
- 연산 가속기 설계
- asynchronous fifo
- cadence conformal eco
- booth multiplier 설계
- 자료구조
- C언어
- malloc
- Sync FIFO
- Today
- Total
JINTBEAT Design Life
Linker - (1) 본문
Linker에서 Symbol이란 ?
주소(또는 값)에 이름을 붙인 것을 말한다.
Symbol이 필요한 이유?
컴파일 단계에서는 변수/함수의 정확한 주소를 모름 → 그래서 이름(Symbol)으로만 관리하는 것
링커가 마지막에
- 실제 메모리 배치를 결정하고
- 각 Symbol에 주소를 Mapping한다.
Example
int global_var = 10;
void func() {
}
컴파일하면 내부적으로 :
Symbol Table
------------
global_var
func
: 아직 주소는 없다.
Linker 이후 :
링커 배치 이후에는
Symbol Table
------------
global_var -> 0x20000000
func -> 0x08000100
이제 실제 주소가 붙는 것이다.
Linker Script에서 Symbol
링커 스크립트에서 직접 심볼을 정의할 수 있다.
_estack = 0x20010000;
의미 : "_estack"이라는 이름의 Symbol을 만들고 값은 0x20010000이다.
실제 많이 쓰는 Symbol들
_sdata
_edata
_sbss
_ebss
_estack
_etext
Linker Script 예시
.data : {
_sdata = .;
*(.data)
_edata = .;
} > RAM
해석 : _sdata의 의미는 data 시작 주소
_edata는 data 끝 주소
extern int _sdata;
extern int _edata;
void init_data() {
int *src = &_etext;
int *dst = &_sdata;
while (dst < &_edata) {
*dst++ = *src++;
}
}
- Linker가 만든 Symbol을 C 코드에서 주소처럼 사용한다.
- Symbol = 이름 + 주소(또는 값)
- 컴파일 단계 → 이름만 있음
- 링크 단계 → 실제 주소가 결정된다.
- C코드에서 extern으로 접근 가능하다.
RW / ZI / RO 개념
| 구분 | 의미 | 특징 |
| RO (Read Only) | 읽기 전용 | Flash에 있음 |
| RW (Read Write) | 초기값 있는 변수 | Flash → RAM 복사 |
| ZI (Zero Init) | 0으로 초기화 | RAM에서 memset |
const int a = 10; // RO
int b = 20; // RW
int c; // ZI
Flash (ROM)
-----------
.text (코드)
.rodata (RO)
.data init (RW 초기값 저장됨)
RAM
-----------
.data (RW 실행 영역)
.bss (ZI)
> .text는 "실행 코드(Instruction)만 있는 영역"
왜 이렇게 배치하지?
- Flash는 읽기만 가능 (실행 가능)
- RAM은 빠르고 쓰기 가능
| 구분 | 어디 있음 | 왜 |
| .text | Flash | 실행만 하면 됨 |
| .rodata | Flash | 읽기만 |
| .data init | Flash | 초기값 저장 |
| .data | RAM | 실행 중 변경 |
| .bss | RAM | 초기화 필요 |
BSS가 뭐지 ?
- 초기 값이 없는 전역 / 정적 변수 영역 (자동으로 0으로 초기화 됨)
int a; // BSS
static int b; // BSS
int c = 0; // 이것도 보통 BSS로 감
- 특징은 초기 값이 없고, 실행 전에 반드시 0으로 채워야 한다.
RAM
-----------
.data → 초기값 있는 변수 (RW)
.bss → 초기값 없는 변수 (ZI)
> BSS는 RAM에만 존재
> Flash에는 없다.
왜 Flash에 안넣나?
> 굳이 저장할 이유가 없으니까 (낭비)
> 그냥 RAM에서 0으로 채우자....가 되는 것이다.
extern int _sbss;
extern int _ebss;
void init_bss() {
int *dst = &_sbss;
while (dst < &_ebss) {
*dst++ = 0;
}
}
> 그래서 부팅 시에 처리한다. 역할은 bss 영역을 전부 0으로 초기화하는 것이다.
왜 이름이 "bss"지 ?
> BSS = Block Started by Symbol
> 초기값 없는 변수들을 위한 RAM 공간이고, 부팅 시 0으로 채워준다.
RW일 때, Flash랑 RAM 모두에 있어야하는 이유는 뭘까 ?
- RW(.data)는 초기 값은 Flash에 저장 + 실행은 RAM에서 해야 하기 때문이다.
왜 RAM에서 실행해야 하나?
int counter = 10;
counter++;
> 이 변수는 계속 바뀐다. 이걸 Flash에 쓸 수는 없다. 쓰기가 너무 느리기 때문이다.
> RW 변수는 반드시 RAM에 있어야 한다.
> 초기 값을 Flash에 저장해주고, 부팅 시에 Flash → RAM 복사가 필요하다.
실제 동작
src = _sidata; // Flash
dst = _sdata; // RAM
while (dst < _edata)
*dst++ = *src++;
Flash (ROM)
-----------
.text
.rodata
.data init ← RW 초기값 저장
RAM
-----------
.data ← 실행 (여기로 복사됨)
.bss
정리하면
- .data는 2개 존재한다. Flash쪽엔 초기값, RAM쪽에서 실제 실행!
Linker 관점
.data : AT(...)
{
_sdata = .;
*(.data)
_edata = .;
} > RAM
_sidata = LOADADDR(.data);
| Symbol | 의미 |
| _sidata | Flash 주소 |
| _sdata | RAM 주소 |
*************************************************************
이 글은 ChatGPT 질의 응답을 바탕으로 작성되었습니다.
*************************************************************
'🖥️ - ARM' 카테고리의 다른 글
| ELF(Executable and Linkable Format) 이란? (2) | 2026.04.12 |
|---|---|
| Linker - (2) (2) | 2026.04.09 |
| ARM I2C 응용 - EEPROM(ATmel) 동작 분석 (1) | 2025.08.13 |
| ARM I2C(Inter-Integrated Circuit) 동작 원리 (7) | 2025.08.10 |
| UART(Universal Asynchronous Receiver/Transmitter)란? (3) | 2025.07.31 |