이전 글에서 ipl 초기 프로그램 로더 만들면서

부트섹터 외 부분은 로드 하지 않음

 

이번에 플로피 디스크 읽도록 수정

 

수정된 ipl.nas 이전 ipl.nas
; hello-os
; TAB=4

ORG 0x7c00 ; 이 프로그램이 어디에 read되는가

; 이하는 표준적인 FAT12 포맷 플로피 디스크를 위한 기술

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바이트를 비어 둔다

; 프로그램 본체

entry:
MOV AX, 0 ; 레지스터 초기화
MOV SS,AX
MOV SP,0x7c00
MOV DS,AX

;디스크 읽기

MOV AX,0x820
MOV ES,AX
MOV CH,0 ; 실린더0
MOV DH,0 ; 헤드 0
MOV CL,2 ; 섹터 2

MOV AH, 0x02 ;AH=0x02; 디스크read
MOV AL, 1 ;1섹터
MOV BX,0
MOV DL,0x00로 ;A드라이브
INT 0x13 ;디스크BIOS 호출
JC error

putloop:
MOV AL,[SI]
ADD SI, 1 ; SI에 1을 더한다
CMP AL,0
JE fin
MOV AH, 0x0e ; 한 글자 표시 Function
MOV BX, 15 ; 칼라 코드
INT 0x10 ; 비디오 BIOS 호출
JMP putloop
fin:
HLT ; 무엇인가 있을 때까지 CPU를 정지시킨다
JMP fin ; Endless Loop

msg:
DB 0x0a, 0x0a ; 개행을 2개
DB "hello, world"
DB 0x0a ; 개행
DB 0

RESB 0x7dfe-$ ; 0x7dfe까지를 0x00로 채우는 명령

DB 0x55, 0xaa
; hello-os
; TAB=4

ORG 0x7c00 ; 이 프로그램이 어디에 read되는가

; 이하는 표준적인 FAT12 포맷 플로피 디스크를 위한 기술

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바이트를 비어 둔다

; 프로그램 본체

entry:
MOV AX, 0 ; 레지스터 초기화
MOV SS,AX
MOV SP,0x7c00
MOV DS,AX
MOV ES,AX

MOV SI,msg
putloop:
MOV AL,[SI]
ADD SI, 1 ; SI에 1을 더한다
CMP AL,0
JE fin
MOV AH, 0x0e ; 한 글자 표시 Function
MOV BX, 15 ; 칼라 코드
INT 0x10 ; 비디오 BIOS 호출
JMP putloop
fin:
HLT ; 무엇인가 있을 때까지 CPU를 정지시킨다
JMP fin ; Endless Loop

msg:
DB 0x0a, 0x0a ; 개행을 2개
DB "hello, world"
DB 0x0a ; 개행
DB 0

RESB 0x7dfe-$ ; 0x7dfe까지를 0x00로 채우는 명령

DB 0x55, 0xaa

 

 

디스크 읽기 설정

- 읽기 : AH=0x02

- 쓰기 : AH=0x03

- DH = 헤드 번호

- DL = 드라이브 번호

- CH = 실린더 번호 & 0xFF

- CL = 섹터번호

 

 

 

일단 책에서 시킨데로 에러는 나오진 않는데 S가 나온다.

S가나오면 안될텐데

 

 

 

 

 

 

책에 설명안된 부분을 안적어서 그랬다.

 

; hello-os
; TAB=4

		ORG		0x7c00			; 이 프로그램이 어디에 read되는가

; 이하는 표준적인 FAT12 포맷 플로피 디스크를 위한 기술

		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바이트를 비어 둔다

; 프로그램 본체

entry:
		MOV		AX, 0			; 레지스터 초기화
		MOV		SS,AX
		MOV		SP,0x7c00
		MOV		DS,AX

;디스크 읽기

		MOV		AX,0x820
		MOV		ES,AX
		MOV		CH,0			; 실린더0
		MOV		DH,0			; 헤드 0
		MOV		CL,2			; 섹터 2

		MOV		AH, 0x02		;AH=0x02; 디스크read
		MOV		AL, 1			;1섹터
		MOV		BX,0
		MOV		DL,0x00로		;A드라이브
		INT		0x13			;디스크BIOS 호출
		JC error
fin:
		HLT					; 무엇인가 있을 때까지 CPU를 정지시킨다
		JMP		fin			; Endless Loop
error:
		MOV		AX,0
		MOV		ES,AX
		MOV		SI,msg
putloop:
		MOV		AL,[SI]
		ADD		SI, 1			; SI에 1을 더한다
		CMP		AL,0
		JE		fin
		MOV		AH, 0x0e		; 한 글자 표시 Function
		MOV		BX, 15			; 칼라 코드
		INT		0x10			; 비디오 BIOS 호출
		JMP		putloop
msg:
		DB		0x0a, 0x0a		; 개행을 2개
		DB		"load error"
		DB		0x0a			; 개행
		DB		0

		RESB	0x7dfe-$		; 0x7dfe까지를 0x00로 채우는 명령

		DB		0x55, 0xaa

 

수정 결과 정상 동작 확인

 

 

 

 

오류시 retry 추가

; hello-os
; TAB=4

		ORG		0x7c00			; 이 프로그램이 어디에 read되는가

; 이하는 표준적인 FAT12 포맷 플로피 디스크를 위한 기술

		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바이트를 비어 둔다

; 프로그램 본체

entry:
		MOV		AX, 0			; 레지스터 초기화
		MOV		SS,AX
		MOV		SP,0x7c00
		MOV		DS,AX

;디스크 읽기

		MOV		AX,0x820
		MOV		ES,AX
		MOV		CH,0			; 실린더0
		MOV		DH,0			; 헤드 0
		MOV		CL,2			; 섹터 2

		MOV		SI,0			;실패 횟수 세는 레지스터

retry:
		MOV		AH, 0x02		;AH=0x02; 디스크read
		MOV		AL, 1			;1섹터
		MOV		BX,0
		MOV		DL,0x00로		;A드라이브
		INT		0x13			;디스크BIOS 호출
		JNC		fin				;에러 없으면 fin으로
		ADD		SI,1			;SI에 1더함
		CMP		SI,5			;SI와 5비교
		JAE		error			; SI>=5 면 error
		MOV		AH,0x00
		MOV		DL,0x00			;A드라이브
		INT		0x13			;드라이브리셋
		JMP		retry

fin:
		HLT					; 무엇인가 있을 때까지 CPU를 정지시킨다
		JMP		fin			; Endless Loop
error:
		MOV		AX,0
		MOV		ES,AX
		MOV		SI,msg
putloop:
		MOV		AL,[SI]
		ADD		SI, 1			; SI에 1을 더한다
		CMP		AL,0
		JE		fin
		MOV		AH, 0x0e		; 한 글자 표시 Function
		MOV		BX, 15			; 칼라 코드
		INT		0x10			; 비디오 BIOS 호출
		JMP		putloop
msg:
		DB		0x0a, 0x0a		; 개행을 2개
		DB		"load error"
		DB		0x0a			; 개행
		DB		0

		RESB	0x7dfe-$		; 0x7dfe까지를 0x00로 채우는 명령

		DB		0x55, 0xaa

 

 

 

 

 

18섹터까지 읽기

 

1장의 디스크

- 80 실린더

- 2 헤드

- 1실린더 = 18섹터

- 1섹터 = 512바이트

- 80 x 2 x 18 x 512 = 1,440kb

 

CL로 섹터 번호 지정. 2 ~ 18섹터까지 반복 읽기수행

; hello-os
; TAB=4

		ORG		0x7c00			; 이 프로그램이 어디에 read되는가

; 이하는 표준적인 FAT12 포맷 플로피 디스크를 위한 기술

		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바이트를 비어 둔다

; 프로그램 본체

entry:
		MOV		AX, 0			; 레지스터 초기화
		MOV		SS,AX
		MOV		SP,0x7c00
		MOV		DS,AX

;디스크 읽기

		MOV		AX,0x820
		MOV		ES,AX
		MOV		CH,0			; 실린더0
		MOV		DH,0			; 헤드 0
		MOV		CL,2			; 섹터 2

readloop:
		MOV		SI,0			;실패 횟수 세는 레지스터
retry:
		MOV		AH, 0x02		;AH=0x02; 디스크read
		MOV		AL, 1			;1섹터
		MOV		BX,0
		MOV		DL,0x00로		;A드라이브
		INT		0x13			;디스크BIOS 호출
		JNC		next			;에러 없으면 fin으로
		ADD		SI,1			;SI에 1더함
		CMP		SI,5			;SI와 5비교
		JAE		error			; SI>=5 면 error
		MOV		AH,0x00
		MOV		DL,0x00			;A드라이브
		INT		0x13			;드라이브리셋
		JMP		retry
next:
		MOV		AX,ES		;어드레스를 0x200 더한다.
		ADD		AX,0x0020	
		MOV		ES,AX		;ADD ES, 0x020이 없어서 이렇게함
		ADD		CL,1		;CL +=1
		CMP		CL,18		;CL과 18비교
		JBE		readloop	; CL <= 18 이면 readloop로

fin:
		HLT					; 무엇인가 있을 때까지 CPU를 정지시킨다
		JMP		fin			; Endless Loop
error:
		MOV		AX,0
		MOV		ES,AX
		MOV		SI,msg
putloop:
		MOV		AL,[SI]
		ADD		SI, 1			; SI에 1을 더한다
		CMP		AL,0
		JE		fin
		MOV		AH, 0x0e		; 한 글자 표시 Function
		MOV		BX, 15			; 칼라 코드
		INT		0x10			; 비디오 BIOS 호출
		JMP		putloop
msg:
		DB		0x0a, 0x0a		; 개행을 2개
		DB		"load error"
		DB		0x0a			; 개행
		DB		0

		RESB	0x7dfe-$		; 0x7dfe까지를 0x00로 채우는 명령

		DB		0x55, 0xaa

 

 

10 실린더 읽기

이전에는 C0-H0-S2 ~ C0-H0-S18까지 읽었는데 이번에는

C9-H1-S18까지 읽어보려고함.

 

맨 위에

CYLS EQU 10으로

CYLS(실린더)=10 설정

; hello-os
; TAB=4


CYLS	EQU		10				; 어디까지 read할지

		ORG		0x7c00			; 이 프로그램이 어디에 read되는가

; 이하는 표준적인 FAT12 포맷 플로피 디스크를 위한 기술

		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바이트를 비어 둔다

; 프로그램 본체

entry:
		MOV		AX, 0			; 레지스터 초기화
		MOV		SS,AX
		MOV		SP,0x7c00
		MOV		DS,AX

;디스크 읽기

		MOV		AX,0x820
		MOV		ES,AX
		MOV		CH,0			; 실린더0
		MOV		DH,0			; 헤드 0
		MOV		CL,2			; 섹터 2

readloop:
		MOV		SI,0			;실패 횟수 세는 레지스터
retry:
		MOV		AH, 0x02		;AH=0x02; 디스크read
		MOV		AL, 1			;1섹터
		MOV		BX,0
		MOV		DL,0x00			;A드라이브
		INT		0x13			;디스크BIOS 호출
		JNC		next			;에러 없으면 fin으로
		ADD		SI,1			;SI에 1더함
		CMP		SI,5			;SI와 5비교
		JAE		error			; SI>=5 면 error
		MOV		AH,0x00
		MOV		DL,0x00			;A드라이브
		INT		0x13			;드라이브리셋
		JMP		retry
next:
		MOV		AX,ES		;어드레스를 0x200 더한다.
		ADD		AX,0x0020	
		MOV		ES,AX		;ADD ES, 0x020이 없어서 이렇게함
		ADD		CL,1		;CL +=1
		CMP		CL,18		;CL과 18비교
		JBE		readloop	; CL <= 18 이면 readloop로
		MOV		CL,1
		ADD		DH,1
		CMP		DH,2
		JB		readloop	;DH<2라면 readloop로
		MOV		DH,0
		ADD		CH,1
		CMP		CH,CYLS
		JB		readloop	;CH<CYLS면 readloop로

fin:
		HLT					; 무엇인가 있을 때까지 CPU를 정지시킨다
		JMP		fin			; Endless Loop
error:
		MOV		AX,0
		MOV		ES,AX
		MOV		SI,msg
putloop:
		MOV		AL,[SI]
		ADD		SI, 1			; SI에 1을 더한다
		CMP		AL,0
		JE		fin
		MOV		AH, 0x0e		; 한 글자 표시 Function
		MOV		BX, 15			; 칼라 코드
		INT		0x10			; 비디오 BIOS 호출
		JMP		putloop
msg:
		DB		0x0a, 0x0a		; 개행을 2개
		DB		"load error"
		DB		0x0a			; 개행
		DB		0

		RESB	0x7dfe-$		; 0x7dfe까지를 0x00로 채우는 명령

		DB		0x55, 0xaa

 

 

중간에 next 부분을 보면

섹터(CL) +1해서 18까지 보내고 

18넘기면 다시 실린더 1 설정

DH 1로 헤더 반대편 확인

DH2가 넘으면 DH = 0으로 다시 헤드 윗면 설정

실린더 CH+1해서 CYLS(10)이 될때까지 루프하도록 동작 

 

next:
		MOV		AX,ES		;어드레스를 0x200 더한다.
		ADD		AX,0x0020	
		MOV		ES,AX		;ADD ES, 0x020이 없어서 이렇게함
		ADD		CL,1		;CL +=1
		CMP		CL,18		;CL과 18비교
		JBE		readloop	; CL <= 18 이면 readloop로
		MOV		CL,1
		ADD		DH,1
		CMP		DH,2
		JB		readloop	;DH<2라면 readloop로
		MOV		DH,0
		ADD		CH,1
		CMP		CH,CYLS
		JB		readloop	;CH<CYLS면 readloop로

 

 

Makefile 수정하기

지금 왜하는건지 설명해주지 않는데

haribote.sys 파일을 만들어서 haribote.img에다가 집어넣는다고 한다. 왜하는진 모르겠는데

 

make file 수정하다보니 알겟는게

초기 프로그램 로더 ipl과 os 본체 haribote.sys를 분리시켜 어셈블한다음 

하나의 img에 합치려고하는듯하다.

 

수정된 makefile

TOOLPATH = ../z_tools/
MAKE     = $(TOOLPATH)make.exe -r
NASK     = $(TOOLPATH)nask.exe
EDIMG    = $(TOOLPATH)edimg.exe
IMGTOL   = $(TOOLPATH)imgtol.com
COPY     = copy
DEL      = del

# 디폴트 동작

default :
	$(MAKE) img

# 파일 생성 규칙

ipl.bin : ipl.nas Makefile
	$(NASK) ipl.nas ipl.bin ipl.lst

haribote.sys : haribote.nas Makefile
	$(NASK) haribote.nas haribote.sys haribote.lst

haribote.img : ipl.bin haribote.sys Makefile
	$(EDIMG)   imgin:../z_tools/fdimg0at.tek \
		wbinimg src:ipl.bin len:512 from:0 to:0 \
		copy from:haribote.sys to:@: \
		imgout:haribote.img

# 커맨드

asm :
	$(MAKE) ipl.bin

img :
	$(MAKE) haribote.img

run :
	$(MAKE) img
	$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin
	$(MAKE) -C ../z_tools/qemu

install :
	$(MAKE) img
	$(IMGTOL) w a: haribote.img

clean :
	-$(DEL) ipl.bin
	-$(DEL) ipl.lst
	-$(DEL) haribote.sys
	-$(DEL) haribote.lst

src_only :
	$(MAKE) clean
	-$(DEL) haribote.img

 

 

 

작성한 os 본체

기존에 ipl.nas 에도 fin이 있던데 문제되지 않나 싶은데

잘은 모르겟지만 ipl.nas 에선 fin앞에까지만 읽어서 문제없는듯하다.

생각해보니 makefile에서 512바이트만 읽도록 하기도 했엇고.

fin:
        HLT
        JMP     fin

 

 

정상동작 확인

 

 

 

 

헥스에디터로보면 0x01ff에 55aa가 들어가있어서 부트섹터가 제대로 들어가있는것같고

 

 

 

 

os본체 파일명은 0x002600에

파일 내용은 0x004200이후에 있다는데 뭘 잘못햇는지 보이질않는다.

 

 

 

 

아무튼 지나가서

OS 본체 동작 확인

320x200x8bit 컬러 모드로 띄우는데 기존 그대로 나온다.

; haribote-os
; TAB=4

        ORG     0xc200      ;프로그램 로딩될곳

        MOV     AL,0x13     ;VGA 그래픽스, 320x200x8bit컬러
        MOV     AH,0x00
        INT     0x10

fin:
        HLT
        JMP     fin

 

 

기존의 ipl.nas next 레이블 끝에

haribote.sys로 넘어가기위한 코드를 안넣어둿기 때문

 

next:
		MOV		AX,ES		;어드레스를 0x200 더한다.
		ADD		AX,0x0020	
		MOV		ES,AX		;ADD ES, 0x020이 없어서 이렇게함
		ADD		CL,1		;CL +=1
		CMP		CL,18		;CL과 18비교
		JBE		readloop	; CL <= 18 이면 readloop로
		MOV		CL,1
		ADD		DH,1
		CMP		DH,2
		JB		readloop	;DH<2라면 readloop로
		MOV		DH,0
		ADD		CH,1
		CMP		CH,CYLS
		JB		readloop	;CH<CYLS면 readloop로


		MOV		[0x0ff0],CH	;IPL이 어디까지 읽엇는지 메모
		JMP		0xc200

 

0xc200으로 넘어가서 동작하면 QEMU가 검은 스크린이 정상적으로 나온다.

 

 

 

 

0xc200인 이유

- 파일 내용이 0x4200 번지부터 시작됨

- 부트섹터 맨앞이 0x8000에 오도록 지정됨

- 0x8000 + 0x4200 = 0xc200의 메모리를 읽어들이기 때문이라는데 0x8000이 어느 부분에서 그렇게 된건지 못찾겟다.

 

 

 

바이오스 다뤄보기

- 바이오스가 16비트 기계어로 되어있어 32비트 모드에선 사용 불가. 32비트 컴파일러(c언어) 쓰기전에 BIOS 설정부터 해보자.

haribote.nas에 부트 정보랑 키보드 LED 상태 저장하도록 수정

; haribote-os
; TAB=4

;BOOT_INFO
CYLS    EQU     0x0ff0      ;부트섹터가 설정
LEDS    EQU     0x0ff1
VMODE   EQU     0x0ff2      ;색수에 관한 정보
SCRNX   EQU     0x0ff4      ;screen x resolution
SCRNY   EQU     0x0ff6      ;screen y resolution
VRAM    EQU     0x0ff8      ;그래픽버퍼의 개시번지


        ORG     0xc200      ;프로그램 로딩될곳

        MOV     AL,0x13     ;VGA 그래픽스, 320x200x8bit컬러
        MOV     AH,0x00
        INT     0x10

        MOV     BYTE [VMODE],8;화면 모드 메모
        MOV     WORD [SCRNX], 320
        MOV     WORD [SCRNY], 200
        MOV     DWORD [VRAM], 0x000a0000

; 키보드 LED 상태를 BIOS가 알려줌
        MOV     AH,0x020
        INT     0x16        ;keyboard BIOS
        MOV     [LEDS],AL
fin:
        HLT
        JMP     fin

 

 

 

c언어 진입하기 부분이 문제다.

기존에 haribote.nas를 수정한 asmhead.nas가 복잡한것도 그런데

bootpack.c를 기계어로 만드는부분 설명이 요란하다.

내가 전에 어떻게 이걸했지?

일단 asmhead.nas

; haribote-os boot asm
; TAB=4

BOTPAK	EQU		0x00280000		; bootpack의 로드 장소
DSKCAC	EQU		0x00100000		; 디스크 캐쉬 프로그램의 장소
DSKCAC0	EQU		0x00008000		; 디스크 캐쉬 프로그램의 장소(리얼모드)

; BOOT_INFO 관계
CYLS	EQU		0x0ff0			; boot sector가 설정한다
LEDS	EQU		0x0ff1
VMODE	EQU		0x0ff2			; 색 가지수에 관한 정보.어떤 비트 칼라인가?
SCRNX	EQU		0x0ff4			; 해상도의 X
SCRNY	EQU		0x0ff6			; 해상도의 Y
VRAM	EQU		0x0ff8			; 그래픽 버퍼의 개시 번지

		ORG		0xc200		; 이 프로그램이 어디에 Read되는가

; 화면 모드를 설정

		MOV		AL, 0x13	; VGA 그래픽스, 320 x200x8bit 칼라
		MOV		AH,0x00
		INT		0x10
		MOV		BYTE [VMODE], 8	; 화면 모드를 메모 한다(C언어가 참조한다)
		MOV		WORD [SCRNX],320
		MOV		WORD [SCRNY],200
		MOV		DWORD [VRAM],0x000a0000

; 키보드의 LED 상태를 BIOS가 가르쳐 준다

		MOV		AH,0x02
		INT		0x16 		; keyboard BIOS
		MOV		[LEDS],AL

; PIC가 일절의 세치기를 받아들이지 않게 한다
;	AT호환기의 사양에서는, PIC의 초기화를 한다면,
;	진한 개를 CLI앞에 해 두지 않으면 이따금 행업 한다
;	PIC의 초기화는 나중에 한다

		MOV		AL,0xff
		OUT		0x21,AL
		NOP				; OUT 명령을 연속하면 잘 되지 않는 기종이 있는 것 같기 때문에
		OUT		0xa1,AL

		CLI				; CPU 레벨에서도 인터럽트 금지

; CPU로부터 1MB이상의 메모리에 액세스 할 수 있도록, A20GATE를 설정

		CALL	waitkbdout
		MOV		AL,0xd1
		OUT		0x64,AL
		CALL	waitkbdout
		MOV		AL, 0xdf	; enable A20
		OUT		0x60,AL
		CALL	waitkbdout

; 프로텍트 모드 이행

[INSTRSET "i486p"]				; 486명령까지 사용하고 싶다고 하는 기술

		LGDT	[GDTR0]			; 잠정 GDT를 설정
		MOV		EAX,CR0
		AND		EAX, 0x7fffffff	; bit31를 0으로 한다(페이징 금지를 위해)
		OR		EAX, 0x00000001	; bit0를 1로 한다(프로텍트 모드 이행이므로)
		MOV		CR0,EAX
		JMP		pipelineflush
pipelineflush:
		MOV		AX,1*8		; read, write 가능 세그먼트(segment) 32bit
		MOV		DS,AX
		MOV		ES,AX
		MOV		FS,AX
		MOV		GS,AX
		MOV		SS,AX

; bootpack의 전송

		MOV		ESI, bootpack	; 전송원
		MOV		EDI, BOTPAK	; 전송처
		MOV		ECX,512*1024/4
		CALL	memcpy

; 하는 김에 디스크 데이터도 본래의 위치에 전송

; 우선은 boot sector로부터

		MOV		ESI, 0x7c00	; 전송원
		MOV		EDI, DSKCAC	; 전송처
		MOV		ECX,512/4
		CALL	memcpy

; 나머지 전부

		MOV		ESI, DSKCAC0+512; 전송원
		MOV		EDI, DSKCAC+512	; 전송처
		MOV		ECX,0
		MOV		CL,BYTE [CYLS]
		IMUL	ECX,512*18*2/4		; 실린더수로부터 바이트수/4에 변환
		SUB		ECX,512/4	; IPL분만큼 공제한다
		CALL	memcpy

; asmhead에서 해야 하는 것은 전부 다 했으므로,
;	나머지는 bootpack에 맡긴다

; bootpack의 기동

		MOV		EBX,BOTPAK
		MOV		ECX,[EBX+16]
		ADD		ECX, 3		; ECX += 3;
		SHR		ECX, 2		; ECX /= 4;
		JZ		skip		; 전송 해야 할 것이 없다
		MOV		ESI,[EBX+20]	; 전송원
		ADD		ESI,EBX
		MOV		EDI,[EBX+12]	; 전송처
		CALL	memcpy
skip:
		MOV		ESP,[EBX+12]	; 스택 초기치
		JMP		DWORD 2*8:0x0000001b

waitkbdout:
		IN		 AL,0x64
		AND		 AL,0x02
		IN		 AL, 0x60	; 빈 데이터 READ(수신 버퍼가 나쁜짓을 못하게)
		JNZ		waitkbdout	; AND결과가 0이 아니면 waitkbdout에
		RET

memcpy:
		MOV		EAX,[ESI]
		ADD		ESI,4
		MOV		[EDI],EAX
		ADD		EDI,4
		SUB		ECX,1
		JNZ		memcpy		; 뺄셈 한 결과가 0이 아니면 memcpy에
		RET
; memcpy는 주소 사이즈 prefix 넣는 것을 잊지 않으면, string 명령에서도 쓸 수 있다

		ALIGNB	16
GDT0:
		RESB	8			; null selector
		DW		0xffff, 0x0000, 0x9200, 0x00cf	; read/write 가능 세그먼트(segment) 32bit
		DW		0xffff, 0x0000, 0x9a28, 0x0047	; 실행 가능 세그먼트(segment) 32 bit(bootpack용)

		DW		0
GDTR0:
		DW		8*3-1
		DD		GDT0

		ALIGNB	16
bootpack:

 

 

 

그래도 길이가 작은 부분은 직접 쳐보자

먼저 bootpack.c

void io_hlt(void);

void HariMain(void)
{

fin:
    io_hlt();
    goto fin;
}

 

naskfunc.nas

;naskfunc
;TAB=4

[FORMAT "WCOFF"]        ;오브젝트 파일 만드는 모드
[BITS 32]               ;32비트모드용 기계어 만듬

;오브젝트 파일ㅇ 위한 정보
[FILE "naskfunc.nas"]   ;소스파일명 정보
    GLOBAL  _io_hlt     ;이프로그램에 포함된 함수명

; 실제 함수

[SECTION .text]         ;오브젝트 파일에서는 이것을 쓴후에 프로그램을 쓴다.
_io_hlt:   ;void io_hlt(void);
    HLT
    RET

 

 

 

 

makefile도 너무 길어졋으므로 그냥 복붙해서 사용

TOOLPATH = ../z_tools/
INCPATH  = ../z_tools/haribote/

MAKE     = $(TOOLPATH)make.exe -r
NASK     = $(TOOLPATH)nask.exe
CC1      = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
OBJ2BIM  = $(TOOLPATH)obj2bim.exe
BIM2HRB  = $(TOOLPATH)bim2hrb.exe
RULEFILE = $(TOOLPATH)haribote/haribote.rul
EDIMG    = $(TOOLPATH)edimg.exe
IMGTOL   = $(TOOLPATH)imgtol.com
COPY     = copy
DEL      = del

# 디폴트 동작

default :
	$(MAKE) img

# 파일 생성 규칙

ipl10.bin : ipl10.nas Makefile
	$(NASK) ipl10.nas ipl10.bin ipl10.lst

asmhead.bin : asmhead.nas Makefile
	$(NASK) asmhead.nas asmhead.bin asmhead.lst

bootpack.gas : bootpack.c Makefile
	$(CC1) -o bootpack.gas bootpack.c

bootpack.nas : bootpack.gas Makefile
	$(GAS2NASK) bootpack.gas bootpack.nas

bootpack.obj : bootpack.nas Makefile
	$(NASK) bootpack.nas bootpack.obj bootpack.lst

naskfunc.obj : naskfunc.nas Makefile
	$(NASK) naskfunc.nas naskfunc.obj naskfunc.lst

bootpack.bim : bootpack.obj naskfunc.obj Makefile
	$(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \
		bootpack.obj naskfunc.obj
# 3MB+64KB=3136KB

bootpack.hrb : bootpack.bim Makefile
	$(BIM2HRB) bootpack.bim bootpack.hrb 0

haribote.sys : asmhead.bin bootpack.hrb Makefile
	copy /B asmhead.bin+bootpack.hrb haribote.sys

haribote.img : ipl10.bin haribote.sys Makefile
	$(EDIMG)   imgin:../z_tools/fdimg0at.tek \
		wbinimg src:ipl10.bin len:512 from:0 to:0 \
		copy from:haribote.sys to:@: \
		imgout:haribote.img

# 커맨드

img :
	$(MAKE) haribote.img

run :
	$(MAKE) img
	$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin
	$(MAKE) -C ../z_tools/qemu

install :
	$(MAKE) img
	$(IMGTOL) w a: haribote.img

clean :
	-$(DEL) *.bin
	-$(DEL) *.lst
	-$(DEL) *.gas
	-$(DEL) *.obj
	-$(DEL) bootpack.nas
	-$(DEL) bootpack.map
	-$(DEL) bootpack.bim
	-$(DEL) bootpack.hrb
	-$(DEL) haribote.sys

src_only :
	$(MAKE) clean
	-$(DEL) haribote.img

 

 

 

검정화면만 나와서 모르겟지만 정상동작하는듯하다.

 

 

 

 

 

day03.zip
0.02MB

+ Recent posts