들어가기에 앞서 레지스터나 세그먼트, 스택에 대해서 간단하게 정리하려 한다.
범용 레지스터
AX(Accumulator) : 산술 연산
BX(Base) : 주소를 가리키는 포인터
CX(Count) : 반복문 횟수
DX(Data) : AX 보조 역할, 큰 수 연산 또는 H/W 포트 I/O 주소 지정
포인터 및 인덱스 레지스터
SI(Source Index) : 데이터를 가져올 출발지
DI(Destination Index) : 데이터를 가져올 목적지
BP(Base Pointer) : 스택 접근 시 기준점(현 함수, 서브 루틴 등의 첫 번째 스택 값)
SP(Stack Pointer) : 현재 스택의 꼭대기 주소
세그먼트 레지스터
CS(Code Segment) : 지금 실행 중인 기계어 코드가 있는 영역
DS(Destination Segment) : 프로그램이 사용하는 변수나 데이터가 있는 영역
SS(Stack Segment) : 스택 메모리 영역
ES(Extra Segment) : DS 보조 공간
제어 및 상태 레지스터
IP(Instruction Pointer) : 다음에 실행할 명령어 주소, PC(Program Counter)랑 같음, 아키텍처에 따라 이름만 다르다.
부트스트랩이란?
컴퓨터에 전원이 들어온 후 무슨 일을 해야하는지 알려주는 것을 부트스트랩이라 한다.
전원이 들어오면 BIOS는 장치 점검 후 마지막 단계로 MBR영역의 첫 512바이트를 메모리로 로드한다.
해당 챕터에서 작성한 프로그램을 플로피디스크를 통해 부팅시키는 것이 목적이다.
[org 0]
[bits 16]
jmp 0x07C0:start
start:
mov ax, cs
mov ds, ax
mov ax, 0xB800
mov es, ax
mov di, 0
mov ax, word [msgBack]
mov cx, 0x7FF
paint:
mov word [es:di], ax
add di, 2
dec cx
jnz paint
mov edi, 0
mov byte [es:edi], 'A'
inc edi
mov byte [es:edi], 0x06
inc edi
mov byte [es:edi], 'B'
inc edi
mov byte [es:edi], 0x06
inc edi
mov byte [es:edi], 'C'
inc edi
mov byte [es:edi], 0x06
inc edi
mov byte [es:edi], '1'
inc edi
mov byte [es:edi], 0x06
inc edi
mov byte [es:edi], '2'
inc edi
mov byte [es:edi], 0x0
inc edi
mov byte [es:edi], '3'
inc edi
mov byte [es:edi], 0x06
inc edi
jmp $
msgBack db '.', 0x67
times 510-($-$$) db 0
dw 0xAA55
far jmp 수행
jmp 0x07C0:start
far jmp란 CS 세그먼트 값을 바꾸는 것을 의미 → 현재 실행 중인 프로그램의 코드 영역으로 주소 값을 옮기는 작업
또한 0x07C0은 인텔 계열 아키텍처에서 고정된 boot sector 주소
세그먼트 값 수정
mov ax, cs
mov ds, ax
위 어셈블리는 결국 mov ds, cs를 의미하게 되는데, 인텔 계열 아키텍처(ex. x86-64)는 세그먼트 값을 수정하려면 범용 레지스터를 거쳐야함
ds와 cs의 값을 맞추는 이유는 ds에 어떤 값이 들어있을지 모르니, cs 코드 영역 부분에서 데이터를 찾게 하기 위해 서로 값을 맞추게 된다.
times 510-($-$$) db 0
509번지까지 0으로 채움 → padding
dw 0xAA55
부트로더의 마지막을 알려주는 역할
0xAA55은 고정 값임, 시스템에서 정해진 값
위 코드를 컴파일 후 vmware에서 플로피디스크에 포함시켜 실행하니 다음과 같은 화면이 나온 것을 확인

프로그램이 부팅된 것을 확인함.(위 사진에선 2의 색깔을 0으로 설정하여 안보임)
위 어셈블리어를 컴파일한 기계어를 다시 디스어셈블 후 확인한 결과이다.
00000000 EA0500C007 jmp word 0x7c0:word 0x5
00000005 8CC8 mov ax,cs
00000007 8ED8 mov ds,ax
00000009 B800B8 mov ax,0xb800
0000000C 8EC0 mov es,ax
0000000E BF0000 mov di,0x0
00000011 A17C00 mov ax,[0x7c]
00000014 B9FF07 mov cx,0x7ff
00000017 268905 mov [es:di],ax
0000001A 83C702 add di,0x2
0000001D 49 dec cx
0000001E 75F7 jnz 0x17
00000020 66BF00000000 mov edi,0x0
00000026 2667C60741 mov byte [es:edi],0x41
0000002B 6647 inc edi
0000002D 2667C60706 mov byte [es:edi],0x6
00000032 6647 inc edi
00000034 2667C60742 mov byte [es:edi],0x42
00000039 6647 inc edi
0000003B 2667C60706 mov byte [es:edi],0x6
00000040 6647 inc edi
00000042 2667C60743 mov byte [es:edi],0x43
00000047 6647 inc edi
00000049 2667C60706 mov byte [es:edi],0x6
0000004E 6647 inc edi
00000050 2667C60731 mov byte [es:edi],0x31
00000055 6647 inc edi
00000057 2667C60706 mov byte [es:edi],0x6
0000005C 6647 inc edi
0000005E 2667C60732 mov byte [es:edi],0x32
00000063 6647 inc edi
00000065 2667C60700 mov byte [es:edi],0x0
0000006A 6647 inc edi
0000006C 2667C60733 mov byte [es:edi],0x33
00000071 6647 inc edi
00000073 2667C60706 mov byte [es:edi],0x6
00000078 6647 inc edi
0000007A EBFE jmp 0x7a
0000007C 2E670000 add [cs:eax],al
00000080 0000 add [bx+si],al
00000082 0000 add [bx+si],al
00000084 0000 add [bx+si],al
....(내용 같음)
000001F8 0000 add [bx+si],al
000001FA 0000 add [bx+si],al
000001FC 0000 add [bx+si],al
000001FE 55 push bp
000001FF AA stosb
jmp 0x07C0: start → jmp word 0x7c0:word 0x5 로 바뀐 것을 확인 가능함.
start: 로 jmp하라는 뜻이므로 start 시작 부분인 00000005 주소인 0x5로 점프한 것으로 바뀐다.
[org 0]은 메모리의 0번지서부터 어셈블리가 시작할 거라고 알려주는 지시어이다.
[bits 16]은 프로그램이 16비트 용이라는 것을 알려주는 선언문이다.
여기서 [org 0]의 0은 10진수이다.
[org 10]이라면 jmp 명령어는 다음과 같이 바뀐다.
jmp word 0x7c0:word 0xf
[org 0x10] 이면 0xf 가 0x16으로 바뀔 것이다.
주의해서 봐야한다.
참고로 jmp $에서 $는 현 위치의 주소 값을 의미하는데, jmp $ 이면 jmp $ 위치로 계속 돌아가라는 뜻이 된다.
Real Mode와 Protected Mode
Real Mode란 컴퓨터가 처음 켜지면 활동하는 모드이다.
예로 MS-DOS가 있는데, 리얼 모드는 프로그램이 한 번에 한 개씩 밖에 동작하지 못한다.
Protected Mode란 현재 운영체제의 동작 모드이다.
프로그램들이 한번에 동작할 수 있다
컴퓨터에 전원이 들어온 후 Real Mode에서 세팅을 맞춘 후 Protected Mode로 전환한다.
Protected Mode의 경우 두 가지로 나뉜다.
유저 모드와 커널 모드로 나뉜다.
'OS > 만들면서 배우는 OS 커널의 구조와 원리' 카테고리의 다른 글
| 6. 보호 (0) | 2026.04.13 |
|---|---|
| 5. 태스크 스위칭, 문맥 교환 (0) | 2026.04.13 |
| 4. 인터럽트와 예외 (0) | 2026.04.10 |
| 3. Protected Mode로 변환 (1) | 2026.04.08 |
| 2. 커널 로드 (0) | 2026.04.06 |