임베디드기사 실기 03 — 시스템 성능·구조 분석 (ARM 어셈블리·엔디안·캐시·페이징·인터럽트)
임베디드기사 실기 03 — 시스템 성능·구조 분석 (ARM 어셈블리·엔디안·캐시·페이징·인터럽트)
출제기준 1-2: 임베디드 시스템 성능 및 구조 분석하기
계산형이 몰려 있는 단원이에요.
엔디안·페이지 수·캐시 적중률은 "공식 + 풀이 과정"만 외우면 점수가 확실합니다!
📎 필기 시리즈의 컴퓨터 구조·마이크로프로세서 편과 함께 보면 좋아요. (링크 추가 예정)
실기 출제 포인트 ⭐⭐⭐
| 키워드 | 핵심 내용 | 빈도 | 기출 |
| ARM 어셈블리 | mov, mvn, orr, str, subs, bne / 루프 횟수 | ⭐⭐⭐ | 2019 Q5, 2021 Q17, 2024 Q5, 2025 Q19 |
| ARM 스택 | stmfd sp!, {fp, lr} → SP 8바이트 감소 |
⭐ | 2025 Q9 |
| 주소 지정 방식 | 상대 주소 = PC + 오프셋 | ⭐ | 2023 Q3 |
| 엔디안 | 빅 엔디안은 상위 바이트가 낮은 주소 | ⭐⭐ | 2016 Q10, 2023 Q4 |
| 캐시 적중률 | 적중 횟수 ÷ 전체 접근 횟수 | ⭐⭐ | 2017 Q18, 2024 Q1 |
| 캐시·TLB | 주소 변환 속도를 높이는 특수 캐시 | ⭐ | 2021 Q2 |
| 가상 메모리·페이징 | 페이지 수 = 영역 크기 ÷ 페이지 크기 | ⭐⭐ | 2017 Q7, 2023 Q18 |
| 버스 | 주소·데이터·제어 버스 | ⭐ | 2019 Q16 |
| 인터럽트 처리 순서 | 요청 → 저장 → 핸들러 호출 → 처리 → 복귀 | ⭐⭐⭐ | 2019 Q7, 2022 Q6 |
| 폴링/벡터/데이지 체인 | 인터럽트 우선순위 판별 방식 비교 | ⭐⭐⭐ | 2015 Q4, 2018 Q14, 2024 Q18 |
키워드 박스 — 답안에 반드시 들어가야 할 단어
엔디안 : 빅=상위 바이트가 낮은 주소 / 리틀=하위 바이트가 낮은 주소
캐시 적중률 : 적중 횟수 ÷ 전체 접근 횟수
TLB : 가상 주소→물리 주소 변환용 캐시 (Translation Lookaside Buffer)
데이지 체인 : 하드웨어, 직렬 연결, 연결 순서(CPU에 가까울수록)로 우선순위
시스템 버스 : 주소 버스 + 데이터 버스 + 제어 버스
FD 스택 : Full Descending — SP를 감소시키며 저장
엔디안 (Endian) ⭐⭐
여러 바이트 데이터를 메모리에 저장할 때, 어느 바이트를 낮은 주소에 놓느냐의 문제예요.
| 방식 | 낮은 주소 | 높은 주소 | 기억법 |
| 빅 엔디안 | 상위 바이트 (MSB) | 하위 바이트 | Big = 큰 쪽이 먼저 |
| 리틀 엔디안 | 하위 바이트 (LSB) | 상위 바이트 | Little = 작은 쪽이 먼저 |
기출 문제
Q. 0x1234를 100번지에 저장할 때 빅 엔디안인 경우 어떻게 저장되는지 16진수로 쓰시오. (2016 Q10)
A.
100번지 : 0x12 (상위 바이트)
101번지 : 0x34 (하위 바이트)
Q. 0xA46B를 빅 엔디안으로 저장했을 때, 8bit 데이터 버스에서 1000번지·1001번지의 값은? (2023 Q4)
A.
1단계: 2자리씩 분리 0xA4 | 0x6B
2단계: 낮은 주소부터 상위 바이트 순서로 저장
1000번지 : 0xA4
1001번지 : 0x6B
⚠️ 함정 1 — 일부 정리본의 해설 표에는 빅 엔디안 1001번지 값이 0xB6으로 잘못 적혀 있어요. 정답은 0x6B 입니다.
(0x6B의 자리를 뒤집으면 0xB6이 되는 오타예요. 바이트 단위로 읽어야지, 숫자 단위로 뒤집으면 안 돼요!)
⚠️ 함정 2 — 리틀 엔디안은 바이트 순서만 바뀌어요. 0xA46B → 6B A4 (비트나 니블이 아니라 바이트 단위)
엔디안 확인 방법:
readelf -h <파일명> → ELF 헤더에서 엔디안 정보 확인
file <파일명> → 32/64비트, 빅/리틀 엔디안 간단 확인
주소 지정 방식 — 상대 주소 ⭐
기출 (2023 Q3) 상대 주소 지정 방식에서 JMP 명령어가 450번지에 있고, 오퍼랜드가 21일 때 실제 물리 주소는?
실제 주소 = PC + 오퍼랜드
명령어 Fetch 후 PC는 다음 명령어를 가리킴
PC = 450 + 1 = 451
실제 주소 = 451 + 21 = 472번지
⚠️ 문제에 "PC가 다음 명령어를 가리킨다"는 전제가 적혀 있지 않아서, 풀이 과정(PC = 451)을 답안에 같이 쓰는 게 안전해요.
과정 없이 472만 쓰면 "450 + 21 = 471 아닌가?" 하고 의심받을 수 있습니다.
참고로 ARM의 ldr에서 자주 보이는 주소 지정 형태는 이거예요.
ldr r2, [r3], #4 ; post-indexed — [r3]에서 4바이트를 읽은 뒤 r3 += 4
캐시와 TLB ⭐⭐
캐시 적중률 (Hit Ratio)
적중률 = 캐시 적중 횟수 ÷ 전체 메모리 접근 횟수
기출 (2017 Q18 = 2024 Q1 동일) CPU가 메모리에 총 2,000회 접근했고 캐시에서 찾은 횟수가 1,350회일 때 적중률을 소수점 셋째 자리까지 구하시오.
적중률 = 1,350 ÷ 2,000 = 0.675 (67.5%)
퍼센트로 써도 정답으로 인정돼요. 단위 지정이 없으면 0.675로 쓰세요.
평균 접근 시간 (응용)
Ta = H × Tc + (1 − H) × Tm
H : 적중률 / Tc : 캐시 접근 시간 / Tm : 주기억장치 접근 시간
연습 (직접 만든 예시):
H = 0.9, Tc = 10ns, Tm = 100ns
Ta = 0.9 × 10 + 0.1 × 100 = 9 + 10 = 19ns
위 식은 미스 시 시간을 Tm 하나로 단순화한 기본 모델이에요.
문제에서 주어진 조건(미스 페널티 등)이 있으면 그 식을 따라가세요.
TLB
기출 (2021 Q2) 가상 주소를 물리 주소로 변환할 때 속도 문제를 해결하기 위해 사용되는 특수 캐시는?
→ TLB (Translation Lookaside Buffer)
TLB 없이: 가상주소 → 페이지 테이블 조회(메모리 접근) → 물리주소 (느림)
TLB 사용: 가상주소 → TLB 조회(캐시) → 물리주소 (빠름)
가상 메모리와 페이징 ⭐⭐
페이지 개수 = 할당된 메모리 영역 크기 ÷ 페이지 1개의 크기
기출 (2017 Q7) 메모리 영역이 0xF000 ~ 0xF7FF이고 페이지 1개가 128워드일 때 페이지 개수는?
영역 크기 = 0xF7FF − 0xF000 + 1 = 0x800 = 2,048 워드
페이지 수 = 2,048 ÷ 128 = 16 페이지
기출 (2023 Q18) I/O 할당 영역이 2,048워드, 페이지 1개당 128워드일 때 페이지 수는?
2,048 ÷ 128 = 2¹¹ ÷ 2⁷ = 2⁴ = 16 페이지
⚠️ 함정: 주소 범위가 주어지면 끝 − 시작 + 1 이에요. +1을 빼먹으면 0x7FF = 2,047이 되어서 틀립니다!
주소 분해 (이해용)
페이지 크기 128워드 = 2⁷ → 페이지 내 오프셋 7비트
페이지 수 16개 = 2⁴ → 페이지 번호 4비트
가상 주소 = [페이지 번호 4비트][오프셋 7비트] (총 11비트 = 2,048워드)
MMU — 가상 주소를 물리 주소로 변환하고 메모리를 보호하는 하드웨어. 변환 시 페이지 테이블을 쓰고, 그 속도를 높이는 것이 TLB 예요.
워킹셋·스레싱·최적 적합 같은 메모리 관리 알고리즘은 10편(3-2)에서 따로 다룹니다.
ARM 어셈블리 ⭐⭐⭐
실기에 가장 많이 나오는 코드 문제 유형이에요. (2019 = 2021 = 2024 동일문제)
기출 (LED 점등 루프)
Q. 0x3000020번지부터 시작하는 8비트 LED를 0x00 ~ 0xFF까지 순차적으로 점등한다. 9번째 비트가 1이면 LED 점등(enable), 0이면 소등(disable)할 때, 다음 ARM 어셈블러 코드의 빈칸을 채우시오.
mov r0, 0x30000000 ; r0 = 베이스 주소
mov r1, #0x000f0000 ; r1 = DELAY 카운트
mov r2, #( ) ; ← 빈칸: r2 = LED 값의 초기값
LOOP
mvn r3, r2 ; r3 = NOT(r2)
orr r4, r3, #0x100 ; r4 = r3 | 0x100 → 9번째 비트(bit 8) SET
str r4, [r0, #0x2000] ; 메모리에 r4 저장 → LED 출력
DELAY
subs r1, r1, #0x01 ; r1 감소 (소프트웨어 지연)
bne DELAY ; r1 != 0이면 DELAY 반복
mov r1, #0x000f0000 ; 지연 카운트 재설정
subs r2, r2, #0x01 ; r2 감소
bne LOOP ; r2 != 0이면 LOOP 반복
A. mov r2, #0xFF (또는 #0x00FF)
왜 0xFF인가?
r2는 0xFF에서 시작해서 1씩 감소 → mvn으로 반전하면 출력값은 0x00부터 1씩 증가
r2 = 0xFF → r3 = NOT(0xFF) = 0x00 → r4 = 0x100 | 0x00 = 0x100
r2 = 0xFE → r3 = 0x01 → r4 = 0x101
r2 = 0x80 → r3 = 0x7F → r4 = 0x17F
→ "0x00부터 순차 점등"이라는 조건 때문에 r2는 감소하는 값, 초기값은 0xFF.
| 명령어 | 의미 |
mov |
레지스터에 값 이동 |
mvn |
값을 반전(NOT) 해서 이동 |
orr |
비트 OR — 특정 비트를 1로 세팅할 때 사용 |
str |
레지스터 값을 메모리에 저장 |
subs |
뺄셈 + 플래그 갱신 (결과가 0이면 Z 플래그 = 1) |
bne |
Z 플래그가 0일 때(결과가 0이 아닐 때) 분기 |
⚠️ 함정: sub가 아니라 subs예요. s가 붙어야 플래그가 갱신되고, 그래야 bne가 동작합니다.
기출 (루프 횟수·처리 바이트 수) — 2025 Q19
mov r1, #64 ; 루프 카운터
Loop:
ldr r2, [r3], #4 ; 4바이트 읽고 r3 += 4 (post-indexed)
add r0, r0, r2 ; 누적 합
subs r1, r1, #1 ; r1 감소 + 플래그
bne Loop ; r1 != 0이면 반복
r1 = 64 → 63 → … → 1 → 0 (0이 되는 순간 종료)
루프 반복 횟수 = 64회
처리한 총 바이트 수 = 64 × 4바이트 = 256바이트
기출 (ARM 스택) — 2025 Q9
Q. ARM에서 stmfd sp!, {fp, lr}을 실행하면 sp가 ( ) 바이트 (증가/감소)된다.
A. 8바이트 감소
stmfd = Store Multiple, Full Descending
레지스터 2개(fp, lr) × 4바이트 = 8바이트
FD 스택은 SP를 먼저 감소시킨 뒤 저장
저장 전 SP = 1000
SP = 1000 − 8 = 992
992번지 ← fp, 996번지 ← lr
| 방식 | Full / Empty | Ascending / Descending | SP 변화 |
| FD | Full | Descending | 감소 (ARM 표준) |
| ED | Empty | Descending | 감소 |
| FA | Full | Ascending | 증가 |
| EA | Empty | Ascending | 증가 |
Full : SP가 마지막으로 저장한 데이터를 가리킴
Empty : SP가 다음에 저장할 빈 칸을 가리킴
push {…} = stmfd sp!, {…} pop {…} = ldmfd sp!, {…}
인터럽트 ⭐⭐⭐
인터럽트 처리 순서
기출 (2019 Q7 = 2022 Q6 동일) 인터럽트 처리 순서를 적으시오.
(1) 현재 동작 중인 주소를 저장한다
(2) 인터럽트 발생 장치가 인터럽트 요청을 한다
(3) 인터럽트 핸들러를 호출한다
(4) 원래의 주소로 복귀한다
(5) 인터럽트 핸들러가 해당 기능을 수행한다
A. (2) → (1) → (3) → (5) → (4)
| 단계 | 하는 일 |
| 요청 (2) | 장치가 CPU에 인터럽트 요청 신호(IRQ)를 보냄 |
| 상태 저장 (1) | PC(복귀 주소)와 레지스터 상태를 스택에 보관 |
| 핸들러 호출 (3) | 인터럽트 벡터 테이블을 참조해 핸들러(ISR) 시작 주소로 분기 |
| 처리 (5) | 핸들러가 장치 요청을 실제로 처리 |
| 복귀 (4) | 저장해둔 주소·상태를 복원하고 원래 프로그램으로 복귀 |
⚠️ 함정: (1)번이 먼저처럼 보이지만 요청(2)이 먼저예요.
요청이 있어야 현재 주소를 저장할 이유가 생기니까요.
인터럽트 우선순위 판별 방식
| 방식 | 구현 | 특징 |
| 폴링 (Polling) | 소프트웨어 | 우선순위 변경 쉽고 회로 단순·융통성 ↑, 인터럽트가 많으면 응답 느림 |
| 벡터 인터럽트 | 하드웨어 | 별도 루틴 없이 응답 빠름, 회로 복잡·융통성 ↓·비경제적 |
| 데이지 체인 | 하드웨어 (직렬) | 장치를 한 회선에 직렬 연결, CPU에 가까운 장치일수록 우선순위 높음 |
기출 (2015 Q4) CPU 외부의 하드웨어적 요구로 프로그램 실행 순서를 변경하는 인터럽트에는 소프트웨어적인 폴링 방식과 하드웨어적인 ( ) 방식이 있다.
→ 데이지 체인
기출 (2018 Q14 = 2024 Q18 동일) 주변장치가 단일 인터럽트 선을 공유하고 연결 순서에 따라 우선순위를 결정하는 방식은?
→ 데이지 체인 (Daisy Chain)
데이지 체인 동작:
장치 하나 이상이 공유 인터럽트 선으로 CPU에 요청
→ CPU가 인지 신호(INTA)를 첫 번째 장치로 전달
→ 요청한 장치는 처리, 요청 안 한 장치는 다음 장치로 신호 통과(Pass)
장점: 회로 단순, 인터럽트 선이 적어도 많은 장치 연결
단점: 장치 수에 비례해 응답 지연 가능, 중간 장치 고장 시 뒤쪽 장치 처리 불가
⚠️ 채점 포인트: 답안에 "단일 회선 공유 + 직렬 연결 + 연결 순서(물리적 위치)로 우선순위"가 들어가야 안전해요.
시스템 버스 ⭐
기출 (2019 Q16) 주변 I/O 장치, 메모리 등 여러 장치의 주소·데이터·제어 신호를 하나의 공용 신호선으로 묶어 CPU와 주고받을 때 이 신호선은?
→ 시스템 버스 (System Bus)
| 버스 | 역할 | 방향 |
| 주소 버스 | 읽고 쓸 메모리/I/O 위치 지정 | 단방향 (CPU → 장치) |
| 데이터 버스 | 실제 데이터 전달 | 양방향 |
| 제어 버스 | 읽기/쓰기 명령, 인터럽트 요청 등 제어 신호 | 양방향/단방향 혼재 |
📌 기출은 없지만 보강: 파이프라인은 필기에서 "Fetch → Decode → Execute" 3단계로 정리돼요.
보기에 "Memory"가 섞여 있으면 함정입니다.
💡 실무에서는?
- 엔디안 — 네트워크 바이트 순서는 빅 엔디안, x86 서버 CPU는 리틀 엔디안이에요. 패킷 캡처를 읽거나
htons/ntohl같은 변환 함수를 쓸 때 이 개념이 그대로 쓰입니다. - 캐시·TLB — 서버 성능 분석에서 캐시 적중률을 보는 이유가 이거예요. TLB 미스가 많은 메모리 집약 워크로드는 HugePages로 개선하기도 합니다.
- 페이징 — 페이지 크기를 키우면 같은 메모리를 더 적은 페이지 엔트리로 관리할 수 있어서 TLB 부담이 줄어요.
- 인터럽트 — 리눅스 서버에서
/proc/interrupts로 NIC 인터럽트가 특정 CPU에 몰려 있는지 보고, IRQ affinity나 irqbalance로 분산하는 게 실무 튜닝 포인트입니다. - ARM — 요즘 서버·엣지 장비에서도 ARM이 늘고 있어서
stmfd,ldr같은 명령어를 읽을 줄 알면 디버깅 때 도움이 돼요.
핵심 정리
✅ 빅 엔디안 = 상위 바이트가 낮은 주소 / 0xA46B → 1000번지 0xA4, 1001번지 0x6B
✅ 상대 주소 = PC(다음 명령어) + 오프셋 → 451 + 21 = 472 (풀이 과정 같이 쓰기)
✅ 캐시 적중률 = 적중 ÷ 전체 → 1,350 ÷ 2,000 = 0.675
✅ TLB = 가상→물리 주소 변환용 캐시
✅ 페이지 수 = 영역 ÷ 페이지 크기 / 영역 = 끝 − 시작 + 1 (+1 주의!)
✅ ARM LED 루프: 빈칸 = mov r2, #0xFF / mvn = NOT / orr = 비트 세트 / subs = 플래그 갱신
✅ stmfd sp!, {fp, lr} → SP 8바이트 감소 (FD 스택)
✅ 인터럽트 순서: (2)→(1)→(3)→(5)→(4)
✅ 폴링 = SW / 벡터·데이지 체인 = HW / 데이지 체인 = 직렬, 가까울수록 우선
✅ 시스템 버스 = 주소(단방향) + 데이터(양방향) + 제어
다음 편에서는 주변장치 분석(출제기준 1-3)으로 이어갑니다!
궁금한 점은 댓글로 남겨주세요!