현재 코드
- 부트 섹터 생성 + 메시지 출력 + putloop 코드에 한번 진입하면 다음 섹터로 넘어감 + 플로피가 안읽히면 다시 시도
- 목표 : 18섹터 까지 읽도록 개선하자
; haribote-ipl
; TAB=4
ORG 0x7c00 ; 메모리 안에서 로딩되는 곳
; 아래는 표준 FAT12 포맷 플로피 디스켓을 위한 내용들
JMP entry
DB 0x90
DB "HARIBOTE" ; 부트섹터 이름. 마음대로해도 ok
DW 512 ; 1섹터 크기(바이트 단위, 512)
DB 1 ; 클러스터 크기(1로 해야됨)
DW 1 ; 예약된 섹터수
DB 2 ; 디스크 FAT 테이블 수
DW 224 ; 루트 디렉토리 엔트리 수 (보통 224엔트리)
DW 2880 ; 디스크 총섹터수
DB 0xf0 ; 미디어 타입
DW 9 ; 하나의 FAT 테이블 섹터 수
DW 18 ; 1트랙에 몇 색터가있는지
DW 2 ; 헤드의 수
DD 0 ; 파티션 없으므로 0
DD 2880 ; 드라이브 크기 한번더씀
DB 0,0,0x29 ; 필요하다고함
DD 0xffffffff ; 볼륨 시리얼 번호
DB "HARIBOTEOS " ; 디스크 이름
DB "FAT12 " ; 포멧이름
RESB 18 ; 18바이트 남김
; 프로그램 본체
entry:
MOV AX,0 ; 레지스터 초기화
MOV SS,AX
MOV SP,0x7c00
MOV DS,AX
; 디스크 읽기
MOV AX,0x0820
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 : 디스크 읽기
MOV AL,1 ; 1 섹터
MOV BX,0
MOV DL,0x00 ; A 드라이브
INT 0x13 ; 디스크 바이오스 호출
JNC next ; 에러가 없으면 next로
ADD SI,1 ; SI에 1더하기
CMP SI,5 ; SI와 5비교
JAE error ; SI >= 5 이면 에러로
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 ; 무한 루프
error:
MOV SI,msg
putloop:
MOV AL,[SI]
ADD SI,1 ; SI에 1 더함
CMP AL,0
JE fin
MOV AH,0x0e ; 한 문자 표시 기능
MOV BX,15 ; 컬러 코드
INT 0x10 ; 비디오 BIOS 호출
JMP putloop
msg:
DB 0x0a, 0x0a ; 줄바꿈 문자 2개
DB "load error"
DB 0x0a ; 줄바꿈
DB 0
RESB 0x7dfe-$ ; 나머지칸 0채우기
DB 0x55, 0xaa
수정된 부분
- retry 레이블에 JNC next와 next 레이블이 추가됨
JBE
- jump if below or equal
- CL이 18보다 같거나 작으면 readLoop로 진입
이 코드가 하는일
1. 섹터 이동
- CL 섹터 번호
2. 번지 지정
- ES 읽어낼 번지
* 0x20은 512/16으로 512를 16진수 표현
=> ES = ES + 0x20로 다음 번지 주소를 가리킴
정리해보자
1. 0x7c00(부트섹터)에서 로드 시작 -> entry로 점프
2. 레지스터들 초기화
2.1 레지스터 초기화
ss 스텍세그먼트, ds 데이터세그먼트 0 입력
sp 스택 포인터 0x7c00 입력
2.2 디스크 읽기 준비
es 버퍼 어드레스 0x0820 읽을 데이터 주소
(es가 0x0820인경우, 세그먼트 레지스터이므로 * 16 => 0x8200을 가리킴)
ch 실린더 해더 0, 해드 0, 섹터 2 선택
si 소스 인덱스 0, 실패 횟수 저장
3. 디스크 읽기 및 에러 검사
3.1 인터럽트 준비
AH = 0x02 디스크 읽기 모드 설정
AL = 1 1번 섹터
BX = 0 세그먼트 레지스터 0(주소 세부 조정용)
DL = 0x00 0번 드라이브 -> 드라이브 A 설정
3.2 인터럽트 호출
INT 0x13 위 인터럽트 관련 값에따라 동작 수행 -> 값읽기 수행
에러가 안뜨면 next로 점프
3.3 next 구문
버퍼 레지스터 주소를 0x0820 + 0x0020. 20씩 이동
add cl,1 섹터 번호++, 다음 섹터번호 지정
cl이 18번을 초과하면 아래의 fin으로 내려감
4. 에러 발생시
4.1 에러 발생시 내려가기
에러 발생시 레지스터 0으로 초기화 후 드라이브 리셋 수행
=> 다시 retry 레이블로 점프
4.2 에러 횟수 5회 초과시
error 레이블로 점프 및 load 에러 출력
haribote00c 정리
1. 부트 섹터 로드
2. 18번 섹터까지 값읽기
3. 에러 발생시 5번 반복. 횟수 초과시 에러 문자 출력
접근한 메모리 번지 범위
- C0-H0-S2 에서 C0-H0-S18까지 접근
- 섹터 1개당 512바이트 => 512 x 17 = 8,704바이트
=> 0x8200 ~ 0xa3ff번지까지 값이 읽혀짐
'컴퓨터과학 > 컴퓨터, OS' 카테고리의 다른 글
os만들기 - 15. os 본체? 만들기 (0) | 2020.08.02 |
---|---|
os만들기 - 14. 10실린더 만큼 읽기 (0) | 2020.08.02 |
os만들기 - 12. 에러 발생시 다시 읽기 (0) | 2020.08.01 |
os만들기 - 11. 버퍼 어드레스와 세그먼트 레지스터 (0) | 2020.08.01 |
os만들기 - 10. make IPL (0) | 2020.08.01 |