컴퓨터가 전원이 켜질 때 BIOS에서 각종 하드웨어의 상태를 체크하고 BIOS의 마지막 임무는 부팅에 사용되는 디스크의 512바이트를 램으로 읽어서 실행합니다. 512바이트 영역을 MBR영역이라고 불리며 BIOS는 롬에 새겨져 있습니다. 이런 과정을 부트스트랩이라고 합니다.
이번 과정에서는 위에서 설명한 512바이트를 만들어 보는 과정을 갖게 됩니다. 512바이트만 만들어도 부팅이 되어 화면에 무언가 문자를 적거나 화면의 색깍을 변경 할 수 있습니다.
바이오스는 MBR을 읽어들여 램의 0x7C00번지에 복사 후 점프합니다. 그렇기 때문에 처음 소스를 작성할 때 0x7C00 부분부터 시작한다는 것을 인지 하셔야 겠습니다.
[org 0] [bits 16] jmp 0x07c0:start ; offset is start: start: mov ax, cs ; 0x07c0 in cs mov ds, ax mov ax, 0xB800 mov es, ax mov di, 0 mov ax, word [msgBack] ; [DS:msgBack] / ax = msgBack value mov cx, 0x7FF
org 0은 offset을 얼마나 줄지 결정 하는 값입니다.
위에서 설명한 내용과 같이 0x7C00 부분부터 시작하니 jmp명령어를 통해서 0x7C00 이동 및 start offset부분으로 이동하여 소스를 실행합니다.
0x07c0:start --> 0x7c00+0x5 = 0x7c05 부분으로 이동
jmp 0x07c0:start 구문 실행 시 0x07c0은 코드 세그먼트(cs)에 offset인 start의 값은 프로그램 카운터(ip)에 저장됩니다.
start: 레이블
현재 cs에는 0x07c0의 값이 들어 있고 데이터 세그먼트(ds)에도 같은 값으로 초기화 시켜줍니다. 이유는 word[msgBack] 부분의 암묵적으로 [DS:msgBack]와 같이 선언 되기 때문에 cs와 ds의 값을 같게 만들어 줘서 제대로 된 값(msgBack에 위치한 값)을 갖고 오도록 해줘야 됩니다.
es에 0xB800 값을 넣는데 이 값이 어디서 나온 것이냐면 pc의 메모리 맵을 확인하면 알 수 있습니다.
0xB800:0000 ~ 0xB800:FFFF 값 까지는 컬러텍스트 모드 비디오 메모리 부분입니다.
이 메모리 위치의 값을 변경하여 화면에 컬러 텍스트를 변경 할 수 있습니다. 그렇기 때문에 이 비디오 메모리 부분의 값을 es에 저장해놓고 차례차례 값을 넣어 화면의 색과 텍스트를 변경 할 것입니다.
word [msgBack]에는 2바이트로 각각 1바이트씩 '.', 0x67 값이 각각 들어 있습니다. (전체 소스 확인)
ax 값(위의 값 대입 용도)과 cx 값(0x7FF 값 만큼 for문 용도)을 초기화 해줍니다.
paint: mov word [es:di], ax ; [0XB800:0] = ax add di, 2 dec cx jnz paint ; zero flag check
paint: 레이블
1. word [es:di] ( [0xB800:0] )에 가리는 위치에 ax('.', 0x67) 값을 입력 해줍니다.
2. di를 2바이트 만큼 증가 시켜줍니다.
3. cx의 값을 1 줄입니다.
4. cx의 값이 0이 아니라면 paint: 레이블로 점프 합니다.
4-1. cx의 값이 0이라면 내려 갑니다.
위아 같이 for문이 다 돌고 나면 아래 소스에는 값을 1바이트씩 각각 입력해줍니다.
mov edi, 0 ; Video memory format is 2Byte mov byte [es:edi], 'A' ; [0XB800:0] = 'A' <- ascii value inc edi mov byte [es:edi], 0x06 ; [0XB800:1] = 0x06 <- 0000(bg color is black ) / 0110(letter color is brown) 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], 0x06 inc edi mov byte [es:edi], '3' inc edi mov byte [es:edi], 0x06 jmp $
jmp $ 명령어는 무한루프를 뜻합니다.
msgBack db '.', 0x67 ; letter('.'), color(bg-brown / letter-white) times 510-($-$$) db 0 dw 0xAA55 ; MBR check
마지막으로 현재 위치 부터 509번지까지 0으로 채우고 510번지 0x55, 511번지에는 0xAA 값을 넣어줍니다.
이 작업은 바이오스가 510, 511번지를 0xAA55 값이 있는지를 확인 하고 있다면 MBR을 확인하는 작업입니다.
실행모습
아직 OS의 기능이 있지는 않으나 부팅이 되는 모습 확인 가능
'Programming > System' 카테고리의 다른 글
[docker] 도커 사용 이유, 심플 예제 및 구동 (기본 사용법) (0) | 2020.05.25 |
---|---|
system에러 - Unable to fetch some archives, maybe run apt-get update... (0) | 2020.04.17 |
안드로이드 에뮬레이터 에서 localhost 접속하기 (장고 서버)(Invalid HTTP_HOST 에러) (0) | 2020.02.20 |
[net_netstate] django, That port is already in use (0) | 2019.01.18 |
[OS] 만들면서 배우는 OS 커널의 구조와 원리-환경 구축 (0) | 2018.12.22 |