彙編函數:ReadSector

在《自己動手寫操作系統》中有個重要的彙編函數ReadSector,作用是通過中斷int 13,從驅動器中讀取開始地址(ax號扇區)後指定數量(cl個)扇區數據到目標地址(es:bp),具體代碼如下:

;----------------------------------------------------------------------------
; 函數名: ReadSector
;----------------------------------------------------------------------------
; 作用:
;	從第 ax 個 Sector 開始, 將 cl 個 Sector 讀入 es:bx 中
ReadSector:
	; -----------------------------------------------------------------------
	; 怎樣由扇區號求扇區在磁盤中的位置 (扇區號 -> 柱面號, 起始扇區, 磁頭號)
	; -----------------------------------------------------------------------
	; 設扇區號爲 x
	;                          ┌ 柱面號 = y >> 1
	;       x           ┌ 商 y ┤
	; -------------- => ┤      └ 磁頭號 = y & 1
	;  每磁道扇區數18    │
	;                   └ 餘 z => 起始扇區號 = z + 1
	push	bp
	mov	bp, sp
	sub	esp, 2			; 闢出兩個字節的堆棧區域保存要讀的扇區數: byte [bp-2]

	mov	byte [bp-2], cl
	push	bx			; 保存 bx
	mov	bl, [BPB_SecPerTrk]	; bl: 除數
	div	bl			; y 在 al 中, z 在 ah 中
	inc	ah			; z ++
	mov	cl, ah			; cl <- 起始扇區號
	mov	dh, al			; dh <- y
	shr	al, 1			; y >> 1 (其實是 y/BPB_NumHeads, 這裏BPB_NumHeads=2)
	mov	ch, al			; ch <- 柱面號
	and	dh, 1			; dh & 1 = 磁頭號
	pop	bx			; 恢復 bx
	; 至此, "柱面號, 起始扇區, 磁頭號" 全部得到 ^^^^^^^^^^^^^^^^^^^^^^^^
	mov	dl, [BS_DrvNum]		; 驅動器號 (0 表示 A 盤)
.GoOnReading:
	mov	ah, 2			; 讀
	mov	al, byte [bp-2]		; 讀 al 個扇區
	int	13h
	jc	.GoOnReading		; 如果讀取錯誤 CF 會被置爲 1, 這時就不停地讀, 直到正確爲止

	add	esp, 2
	pop	bp

	ret

其中最重要的是:

1、傳入的扇區起始號(ax)是邏輯編號(即從0開始),所以有了inc ah這行代碼。因爲軟盤的扇區號是從 0柱面0磁頭1扇區開始編號的。

2、商y的編碼方式爲 7位柱面號 + 1位磁頭號,2^7 = 128 > 80(每面的磁道數或柱面數)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章