【问题标题】:How are all disk sectors iterated in assembly?如何在汇编中迭代所有磁盘扇区?
【发布时间】:2015-06-22 22:27:41
【问题描述】:

在学习汇编的过程中,我正在编写一个操作系统。我已经成功编写了将第二个 512 字节扇区附加到初始 512 字节引导加载程序所需的代码:

%define KBDINT  0x16
%define VIDINT  0x10
%define DISKINT 0x13
%define TTYOUT  0x0E
%define VIDMODE 0x0000
%define NUL 0x00
%define CR  0x0D
%define LF  0x0A
%define START   0x7C00

%macro  PRINT   1
    mov si, %1
    call    print
%endmacro

    bits    16          ; 16 bit real mode
    org START           ; loader start in memory
start:  jmp main

print:  jmp .init
.loop:  mov bx, VIDMODE
    mov ah, TTYOUT
    int VIDINT
    inc si
.init:  mov al, [si]
    cmp al, NUL
    jne .loop
    ret

main:   cli
    xor ax, ax
    mov ds, ax
    mov es, ax
    sti
    PRINT   welcome

    mov ah, NUL
    int DISKINT
    mov al, 0x01        ; sector count
    mov ah, 0x02        ; read function
    mov bx, kernel
    mov cl, 0x02
    mov ch, 0x00        ; cylinder number
    mov dh, 0x00        ; head number
    int DISKINT
    jc  fail
    jmp kernel

fail:   PRINT   failure
;   jmp halt

halt:   PRINT   halting
    cli
    hlt
    PRINT   imprbbl
    jmp halt

    welcome db "moose os", CR, LF, NUL
    failure db "failed disk load", CR, LF, NUL
    halting db "halting", CR, LF, NUL
    imprbbl db "but that's impossible!", CR, LF, NUL

times 0x0200 - ($ - $$) - 2 db 0x00
    end dw 0xAA55

kernel: PRINT   yay
    yay db "kernel", CR, LF, NUL
    jmp halt

times 0xFFFF db 0x00

我编译文件时使用:nasm -f bin -o boot.bin boot.asm && qemu boot.bin:

我很好奇磁头和气缸是如何使用的:

  • 扇区是如何迭代的?
  • 模拟和直接执行之间的迭代有何不同?

【问题讨论】:

  • 图像文件中有那个扇区吗?从您粘贴的来源和命令来看,您甚至没有 2 个扇区,更不用说 3 个了。
  • @Jester hmm lemme try something
  • @Jester 是的,这就是问题所在。我真傻
  • 见这里:wiki.osdev.org/…。调用 INT13h AH=8 BIOS 函数以获取“驱动器几何”。然后迭代直到最大值。
  • 最好将jmp halt 放在yay db "kernel", CR, LF, NUL 之前。现在你执行垃圾,这是一件有风险的事情!

标签: assembly bootloader


【解决方案1】:

•这些部门是如何迭代的?

要使用 CHS CylinderHeadSector 表示法迭代多个扇区,我们 首先必须检索这些参数的实际限制。 BIOS有功能 int 13h 上的 08h,它为我们提供了 最大 值以及一些额外的值 我们暂时不需要的信息。

CL 中的扇区号范围为 1 到 63。
DH 中的头号范围从 0 到 255,虽然很少使用 255。
CL 中的柱面编号范围从 0 到 1023。由于这不能保存在 一个字节,这个 10 位数的最高 2 位存储在位 6 和7个CL寄存器!

迭代的工作原理

把 CHS 符号想象成某种数字,其中 C 是 最重要的部分,S 是最不重要的部分。
为了到达磁盘上的下一个扇区,我们开始增加 this 数字在其最不重要的一端。
如果通过增加 S 部分超出其范围,我们将其重置为 最小值 (1) 并开始递增下一个更重要的部分 在这种情况下是 H
如果通过增加 H 部分超出其范围,我们将其重置为 最小值 (0) 并开始递增最重要的部分 在这种情况下是 C
如果通过增加 C 部分超出其范围,我们将其重置为 最小值 (0)。这将在磁盘上进行环绕。如果在输入 给出了正确的 SectorCount 然后通常此时读数将具有 停止了。

; INPUT:  DL=Drive
;         CH=Cylinder
;         DH=Head
;         CL=Sector
;         AX=SectorCount
;         ES:BX=Buffer
; OUTPUT: CF=0 AH       = 0
;              CH,DH,CL = CHS of following sector
;         CF=1 AH       = Error status
;              CH,DH,CL = CHS of problem sector
ReadDiskSectors:
  push    es
  push    di
  push    bp
  mov     bp,sp           ;Local variables:
  push    ax              ;[bp-2]=SectorCount
  push    cx              ;[bp-4]=MaxSector
  push    dx              ;[bp-6]=MaxHead
  push    bx              ;[bp-8]=MaxCylinder

  push    es
  mov     ah,08h
  int     13h             ;ReturnDiskDriveParameters
  pop     es
  jc      NOK
  mov     bx,cx           ;10-bit cylinder info -> BX
  xchg    bl,bh
  shr     bh,6
  xchg    [bp-8],bx       ;Store MaxCylinder and get input BX back
  movzx   dx,dh           ;8-bit head info -> DX
  xchg    [bp-6],dx       ;Store MaxHead and get input DX back
  and     cx,003Fh        ;6-bit sector info -> CX
  xchg    [bp-4],cx       ;Store MaxSector and get input CX back

ReadNext:
  mov     di,5            ;Max 5 tries per sector
ReadAgain:
  mov     ax,0201h        ;Read 1 sector
  int     13h             ;ReadDiskSectors
  jnc     OK
  push    ax              ;Save error status byte in AH
  mov     ah,00h
  int     13h             ;ResetDiskSystem
  pop     ax
  dec     di
  jnz     ReadAgain
  stc
  jmp     NOK
OK:
  dec     word ptr [bp-2] ;SectorCount
  jz      Ready
  call    NextCHS
  mov     ax,es           ;Move buffer 512 bytes up
  add     ax,512/16
  mov     es,ax
  jmp     ReadNext

Ready:
  call    NextCHS         ;Return useful CHS values to support reads
  xor     ah,ah           ; -> CF=0 ... that are longer than memory
NOK:
  mov     sp,bp
  pop     bp
  pop     di
  pop     es
  ret

NextCHS:
  mov     al,cl            ;Calculate the 6-bit sector number
  and     al,00111111b
  cmp     al,[bp-4]        ;MaxSector
  jb      NextSector
  cmp     dh,[bp-6]        ;MaxHead
  jb      NextHead
  mov     ax,cx            ;Calculate the 10-bit cylinder number
  xchg    al,ah
  shr     ah,6
  cmp     ax,[bp-8]        ;MaxCylinder
  jb      NextCylinder
DiskWrap:
  mov     cx,1             ;Wraparound to very first sector on disk
  mov     dh,0
  ret
NextCylinder:
  inc     ax
  shl     ah,6             ;Split 10-bit cylinder number over CL and CH
  xchg    al,ah
  mov     cx,ax
  mov     dh,0
  inc     cl
  ret
NextHead:
  inc     dh
  and     cl,11000000b
NextSector:
  inc     cl
  ret

关于扇区大小的说明

虽然在其中包含不是 512 字节的扇区是完全可以的 长度,这是一个保存假设,它们将是那个大小。 经过数十年的编程,我从未见过没有 512 字节的磁盘 部门。
如果你坚持支持不同的大小,可以看第4个字节 您从 ES:DI 中收到指针的 DisketteParameterTable 的 BIOS 函数 ReturnDiskDriveParameters。

•模拟和直接执行之间的迭代有何不同?

我想通过直接执行你了解真正的硬件。
对于真正的硬件 BIOS 将以 CHS 表示法返回您的几何形状,并且扇区存在......好吧,只是因为它们是真实的!
在仿真下,仿真器将尽最大努力为您提供这些几何值,但您需要确保相关驱动器上存在足够的扇区。这正是@Jester 在问你时所说的:“你的图像文件中有那个扇区吗?”您通过使用times 0xFFFF db 0x00放大图像文件解决了这个问题

一些额外的建议

您没有设置堆栈。由于您在 7C00h 将内核加载到引导扇区上方,因此我建议您将 SS:SP 初始化为 0000h:7C00h 以用于引导扇区下方的堆栈。

main:
  cli
  xor ax, ax
  mov ds, ax
  mov es, ax
  mov ss, ax
  mov sp, 7C00h
  sti
  PRINT   welcome

正如@Fifoernik 所说,您最好将jmp halt 放在yay db "kernel", CR, LF, NUL 之前,以防止执行此数据!

kernel:
  PRINT   yay
  jmp halt
  yay db "kernel", CR, LF, NUL

【讨论】:

  • 实际上现在几乎所有出售的硬盘都使用 4096 字节扇区。它们都假装有 512 字节的扇区,因为几十年来程序员一直认为它们不能是任何其他长度。
  • 我记得有一个古老的 IBM-PC 8 英寸驱动器,我相信它是 1024 字节。从 CP/M 迁移文件很方便。
  • 当然 int 13h/08h 会受到支持的硬盘大小的限制。如果您想支持更大的硬盘驱动器、CD、USB 记忆棒,您可能需要检查是否支持扩展磁盘 bios 功能,然后使用 int 13h/42h
  • @MichaelPetch 我记得 30 年前在工作中看到过那些非常大的软盘,但即便如此,它们也不再旋转了。它们曾用于穿孔带驱动的铣床,是后来 CNC 机床的祖先。
猜你喜欢
  • 2018-02-21
  • 2019-12-05
  • 2013-10-05
  • 1970-01-01
  • 2011-06-21
  • 2022-01-23
  • 2021-07-12
  • 2021-09-03
  • 1970-01-01
相关资源
最近更新 更多