;ipl.nas
;---------------------------------------------------------------
; 플로피 디스크의 정보
ORG 0x7c00
JMP entry
DB 0x90
DB "HELLOIPL" ; boot sector이름을 자유롭게 써도 좋다(8바이트)
DW 512 ; 1섹터 크기(512로 해야 함)
DB 1 ; 클러스터 크기(1섹터로 해야 함)
DW 1 ; FAT가 어디에서 시작될까(보통은 1섹터째부터)
DB 2 ; FAT 개수(2로 해야 함)
DW 224 ; 루트 디렉토리 영역의 크기(보통은 224엔트리로 한다)
DW 2880 ; 드라이브 크기(2880섹터로 해야 함)
DB 0xf0 ; 미디어 타입(0xf0로 해야 함)
DW 9 ; FAT영역의 길이(9섹터로 해야 함)
DW 18 ; 1트럭에 몇 개의 섹터가 있을까(18로 해야 함)
DW 2 ; 헤드 수(2로 해야 함)
DD 0 ; 파티션을 사용하지 않기 때문에 여기는 반드시 0
DD 2880 ; 드라이브 크기를 한번 더 write
DB 0,0,0x29 ; 잘 모르지만 이 값으로 해 두면 좋은 것 같다
DD 0xffffffff ; 아마, 볼륨 시리얼 번호
DB "HELLO-OS " ; 디스크 이름(11바이트)
DB "FAT12 " ; 포맷 이름(8바이트)
RESB 18 ; 우선 18바이트를 비어 둔다(NASK에서는 18바이트만큼 0으로 채움)
; 프로그램 본체
entry:
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 di, 0
mov byte [es:di], 'A'
inc di
mov byte [es:di], 0x06
inc di
mov byte [es:di], 'B'
inc di
mov byte [es:di], 0x06
inc di
mov byte [es:di], 'C'
inc di
mov byte [es:di], 0x06
inc di
mov byte [es:di], '1'
inc di
mov byte [es:di], 0x06
inc di
mov byte [es:di], '2'
inc di
mov byte [es:di], 0x06
inc di
mov byte [es:di], '3'
inc di
mov byte [es:di], 0x06
jmp $
msgBack db '.', 0x67
times 510-($-$$) db 0
dw 0xAA55
;---------------------------------------------------------------
ORG 0x7c00
프로그램상의 오프셋의 기준 값을 0x7c00으로 설정하는 것입니다.
바이오스가 디스크의 MBR(첫 512 바이트)을 읽어들여 램의 물리 주소 0x07c00 번지에 복사한 후 0x700으로 점프 하게 됩니다. 그렇기 때문에 오프셋을 0x7c00으로 설정하여 그 다음부터 프로그램이 실행 될 수 있도록 하는 것입니다.
JMP entry
entry 레이블로 점프 합니다.
DB 0x90
DB "HELLOIPL" ; boot sector이름을 자유롭게 써도 좋다(8바이트)
DW 512 ; 1섹터 크기(512로 해야 함)
DB 1 ; 클러스터 크기(1섹터로 해야 함)
DW 1 ; FAT가 어디에서 시작될까(보통은 1섹터째부터)
DB 2 ; FAT 개수(2로 해야 함)
DW 224 ; 루트 디렉토리 영역의 크기(보통은 224엔트리로 한다)
DW 2880 ; 드라이브 크기(2880섹터로 해야 함)
DB 0xf0 ; 미디어 타입(0xf0로 해야 함)
DW 9 ; FAT영역의 길이(9섹터로 해야 함)
DW 18 ; 1트럭에 몇 개의 섹터가 있을까(18로 해야 함)
DW 2 ; 헤드 수(2로 해야 함)
DD 0 ; 파티션을 사용하지 않기 때문에 여기는 반드시 0
DD 2880 ; 드라이브 크기를 한번 더 write
DB 0,0,0x29 ; 잘 모르지만 이 값으로 해 두면 좋은 것 같다
DD 0xffffffff ; 아마, 볼륨 시리얼 번호
DB "HELLO-OS " ; 디스크 이름(11바이트)
DB "FAT12 " ; 포맷 이름(8바이트)
RESB 18 ; 우선 18바이트를 비어 둔다(NASK에서는 18바이트만큼 0으로 채움)
플로피 디스크에 대한 정보를 저장합니다. 자세한 내용은 아직 잘 모르겠습니다. 후에 추가해야 할듯..
entry:
mov ax, cs
mov ds, ax
cs(코드세그먼트)와 ds(데이터 세그먼트)를 같게 합니다.
이는 세그먼트를 지정하지 않고 데이터를 사용하면 CPU는 묵시적으로 DS에 있는 값을 세그먼트로 사용하겠다고 인식하게 됩니다. 만약 CS와 DS를 같게 해주지 않는다면 원치 않는 데이터를 읽거나 쓸게 될수도 있습니다.
mov ax, 0xB800
mov es, ax
es 세그먼트에 0xB800을 넣습니다.
0xB800를 넣는 이유는 컬러 텍스트 모드로 비디오 메모리를 사용하기 위해서 입니다.
컬러 텍스트 모드는 0xB800:0000번지에서 0xB800:FFFF 의 한 개의 세그먼트 영역을 사용하여 모니터에 글씨를 문자로 단위로 나타내거나 그림을 픽셀 단위로 나타냅니다.
글자를 나타내는 대에는 1바이트의 아스키 코드 값과 4비트의 배경색, 4비트의 글자색으로 총 2바이트로 나타냅니다. 예를 들어 화면의 젤 위의 첫번째 칸에 ‘A’라는 흰색바탕에 검은 글씨를 나타내고 싶다면
0xB800:0000번지에는 0x65를 넣고 0xB800:0001번지에는 0x70넣으면 됩니다.
mov di, 0
mov ax, word [msgBack]
mov cx, 0x7FF
di값은 시작 번지부터 다음 번지로 이동하기 위해 사용되는 변수고, ax 레지스터에는 msgBack이 가리니키는 값을 넣습니다 msgBack는 밑에 db ‘.’, 0x67 로 정의되어 있는데, 이는 갈색 바탕의 흰색 점입니다.
그리고 cx 레지스터에는 데이터를 넣을 길이입니다.
paint:
mov word [es:di], ax
add di, 2
dec cx
jnz paint
실제로 그려지는 부분입니다.
바로 위에서 ax레지스터에 갈색 바탕에 흰색 점을 뜻하는 값이 저장되어 있었습니다.
es:di 위치에 점을 찍고 di값을 증가 시킨후 cx값을 1 감소 시켰습니다. 그리고 zero 플래그를 체크한뒤 다시 paint 레이블로 점프를 합니다. 즉, cx값이 0이 될때까지 es:0부터 오프셋값을 2씩 증가시키면서 점을 찍는 코드가 되겠습니다.
mov di, 0
mov byte [es:di], 'A'
inc di
mov byte [es:di], 0x06
다시 di 값을 0으로 초기화 하여 화면 맨 위에 첫번째칸을 가리키기 한후 ‘A’라는 검은색 바탕에 갈색 글자를 나타내게 하였습니다. 그 뒤에 ‘B’, ‘C’, ‘1’, ‘2’, ‘3’ 도 마찬가지입니다.
코드 색상
0x0(0000) 검은색
0x1(0001) 파란색
0x2(0010) 녹색
0x3(0011) 하늘색
0x4(0100) 빨간색
0x5(0101) 보라색
0x6(0110) 갈색
0x7(0111) 흰색jmp $
$표시는 현재 수행하고 있는 명령어의 주소값을 가르킵니다. 즉, 현재 수행하고 있는 명령어의 주소값으로 점프하라는 명령어이므로 while(1)처럼 계속 반복하게 하는 코드입니다.
times 510-($-$$) db 0
dw 0xAA55
times 510-($-$$) db 0 명령은 현재 번지에서부터 509번까지 0으로 채우라는 명령입니다.
그리고 510번지에는 0x55를 511번지에는 0xAA를 넣게 되는데, 이것은 PC가 부팅할때 바이오스는 디스크의 MBR 부분을 램으로 복사하면서 이 곳이 프로그래머가 지정한 MBR인지 확인을 하는데 이때 체크하는 값이 MBR의 제 끝의 1워드 값입니다. 이 값이 “0xAA55”면 MBR으로 판단하게 됩니다.