728x90

현재 코드

- 부트 섹터 생성 + 메시지 출력 + 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번지까지 값이 읽혀짐

 

 

 

 

 

 

300x250

+ Recent posts