| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 | 31 |
Tags
- 개발
- 코딩
- React Native
- 소프트웨어학과
- 정보보호
- IT
- 프로그래밍
- 플러그인
- bob 14기
- 프로젝트
- 소프트웨어
- BOB
- 코틀린
- 해킹
- 후기
- 악성코드
- QEmu
- 학부연구생
- 정보보안
- CPU
- Kotlin
- 보안
- 보안제품개발
- 앱
- 애플리케이션
- 앱 개발
- 산학
- Android Studio
- 화이트햇스쿨
- 프론트엔드
Archives
- Today
- Total
맨땅에 코딩
CPU 동작 원리 핵심 정리(QEMU·플러그인 관점) 본문
분명 컴퓨터구조 시간에 배웠던 것 같은데, 하나도 기억이 나지 않아서 정리해봅니다.
1. CPU의 역할
CPU는 명령어를 하나씩 읽고 실행하는 "두뇌"이다.
기본 반복 구조는 다음과 같다.
1. Fetch → 메모리에서 명령어 가져오기
2. Decode → 어떤 연산인지 해석하기
3. Execute → 실제 연산 수행하기 (레지스터/메모리 변경)
4. Repeat → 다음 명령어로 이동
이를 명령어 사이클이라고 하는데,
QEMU는 이 사이클을 소프트웨어적으로 시뮬레이션 하는 것이다.
2. 레지스터
CPU 내부의 초고속 저장공간으로
메모리보다 훨씬 빠르고, 명령어 대부분이 레지스터 간 연산이다.
| 이름 | 역할 |
| RIP (Instruction Pointer) | 다음에 실행할 명령어의 주소 (Program Counter) |
| RSP (Stack Pointer) | 현재 스택의 최상단 주소 |
| RBP (Base Pointer) | 현재 함수 프레임의 기준 주소 |
| RAX, RBX, RCX, RDX | 범용 레지스터 (데이터 연산용) |
| FLAGS (EFLAGS/RFLAGS) | 연산 결과 상태(Zero, Carry 등) 저장 |
| CR3 (Page Table Base) | 현재 페이지 테이블의 물리주소 (메모리 매핑 기준) |
플러그인은 이 레지스터 값을 "명령어 실행 시점마다" 읽어서 로그로 남길 수 있다.
[Exec] RIP=0x401000 | RAX=0x00000001 | RBX=0x00000002
3. 명령어의 실제 예시
CPU는 다음과 같은 기계어 명령을 실행한다.
| 어셈블리 | 의미 | 결과 |
| mov eax, 5 | 5를 레지스터 eax에 넣음 | eax = 5 |
| add eax, ebx | eax = eax + ebx | eax 값이 바뀜 |
| cmp eax, ebx | 두 값 비교 | FLAGS 업데이트 |
| jmp 0x401000 | 특정 주소로 점프 | RIP 바뀜 |
| call 0x404000 | 함수 호출 | 스택에 리턴주소 푸시 |
| ret | 함수 리턴 | 스택에서 주소 팝 |
플러그인은 이런 "명령어 단위 이벤트"가 일어날 때마다 콜백을 받게 된다.
즉, "어떤 주소에서 어떤 명령이 실행됐는가"를 추적할 수 있는 구조다.
4. 메모리 접근(Memory Access)
CPU가 데이터를 쓸 때는 항상 다음 단계로 작동한다.
레지스터 → 가상 주소 → 물리 주소 → 실제 메모리
이것을 MMU가 담당하고,
CR3 레지스터에 있는 페이지 테이블을 기준으로 주소를 변환한다.
mov [0x7ffdf000], eax
위 한 줄을 실행하면,
- CPU는 0x7ffdf000 이라는 가상 주소를 받음
- MMU가 페이지 테이블을 보고 물리주소(예: 0x12345000)로 변환
- 실제 메모리에 쓰기(write) 발생
QEMU 플러그인은 이때 "메모리 접근 이벤트"를 잡을 수 있다.
[MEM_WRITE] VA=0x7ffdf000 → PA=0x12345000 | Size=4
5. 인터럽트와 예외
CPU가 원래 실행하던 일을 멈추고 "다른 중요한 일"을 처리하는 순간
| 이벤트 | 설명 |
| 타이머 인터럽트 | 일정 주기로 CPU 깨워 스케줄러 동작 |
| I/O 인터럽트 | 키보드 입력, 네트워크 수신 등 |
| 시스템콜 인터럽트 | 프로그램이 커널 기능을 요청할 때 (int 0x80, syscall) |
| 페이지 폴트 예외 | 없는 페이지 접근 시 발생 |
플러그인은 이런 이벤트 발생 시점에 "IRQ 번호, 발생 주소, 핸들러 진입 주소"를 기록함
[IRQ] #14 Page Fault @ 0xfffff80212345678
6. 함수 호출 스택
함수가 호출될 때, CPU는 현재 상태를 스택에 저장
call func_A → [리턴주소] push → RIP 이동
ret → [리턴주소] pop → 복귀
7. 전체 CPU 실행 사이클 흐름
while (1) {
Fetch: instr = Memory[RIP];
Decode: type = parse(instr);
Execute: do_operation(instr);
Update: RIP += instr.length;
}
QEMU는 이 과정을 "TCG(Tiny Code Generator)"로 소프트웨어화해서, 실제 CPU처럼 동작하게 만든다.
8. QEMU와 CPU의 연결
게스트 OS → 명령어 실행
↓
QEMU (TCG) → 명령어를 해석·에뮬레이트
↓
플러그인 → 콜백 실행 (on_exec)
즉, 실제 CPU는 전자회로로 명령을 처리하지만, QEMU는 C언어로 그 과정을 재현한다.
우리가 만들고자 하는 플러그인은 "그 시점의 상태를 옆에서 기록"하는 구조이다.
'낙서장' 카테고리의 다른 글
| QEMU 그게 뭔데? (0) | 2025.10.26 |
|---|---|
| 메모리 구조 핵심 요약(QEMU·플러그인 관점) (0) | 2025.10.26 |
| 운영체제 그게 뭔데?(QEMU·플러그인 관점) (0) | 2025.10.26 |
| 유니스트 컴퓨터공학과 대학원 전기 1차 합격 후기 (0) | 2025.09.25 |
| 추억용으로 남기는 대학 입시 일기 (1) | 2025.09.20 |
