如何所有的磁盘扇区组装迭代? [英] How are all disk sectors iterated in assembly?

查看:175
本文介绍了如何所有的磁盘扇区组装迭代?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在学习汇编的过程中,我写的操作系统。我已经成功写入必要的code对追加第二个512字节扇区最初的512字节的引导程序:

 %定义KBDINT 0x16
%定义VIDINT为0x10
%定义DISKINT 0x13
%定义TTYOUT为0x0E
%定义为0x0000 vidmode运行
%定义NUL为0x00
%定义CR 0X0D
%定义LF的0x0A
%定义开始0x7C00%宏PRINT 1
    MOV SI,1%
    调用打印
%endmacro    位16; 16位实模式
    组织START;在内存中加载程序启动
启动:JMP主打印:JMP .init
.loop:MOV BX,vidmode运行
    MOV啊,TTYOUT
    INT VIDINT
    INC SI
.init:MOV人,[SI]
    CMP人,NUL
    JNE .loop
    RET主:CLI
    异斧,斧
    MOV DS,AX
    MOV ES,AX
    STI
    PRINT欢迎    MOV啊,NUL
    INT DISKINT
    MOV等,为0x01;扇区计数
    MOV啊,0X02;读取功能
    MOV BX,内核
    MOV CL,0X02
    MOV CH,0×00;柱面号
    MOV DH,0×00;头数
    INT DISKINT
    JC失败
    JMP内核失败:PRINT失败
; JMP叫停暂停:暂停打印
    CLI
    HLT
    PRINT imprbbl
    JMP叫停    欢迎DB驼鹿OS,CR,LF NUL
    失败分贝故障磁盘负荷,CR,LF NUL
    暂停DB停止,CR,LF NUL
    imprbbl分贝,但是这是不可能的!,CR,LF NUL次0x0200 - ($ - $$) - 2分贝为0x00
    结束DW 0xAA55将内核:PRINT耶
    耶DB内核,CR,LF NUL
    JMP叫停次0xFFFF的分贝为0x00

我编译的文件: NASM -f斌-o BOOT.BIN boot.asm&放大器;&安培; QEMU BOOT.BIN

我很好奇,怎么头和气瓶使用:


  • 如何在部门通过迭代?

  • 仿真和直接执行之间如何迭代有什么不同?


解决方案

  

•如何在部门通过迭代?


要使用的 CHS CylinderHeadSector符号迭代许多部门,我们
首先必须检索这些参数的实际限制。 BIOS中有功能
08H在 INT 13H ,让我们在最大值,以及一些额外的
信息,我们不需要现在。

在CL的扇区数为1至63结果
在DH头数的取值范围为0〜255,虽然255是很少使用。结果
在CL气缸数目的范围从0到1023由于这不能在举行
一个字节,该10比特数的2的最高位存储在第6位
和CL的7注册!

的迭代是如何工作的

想想CHS表示法,就好像它是某种多项,其中的 C
最显著的部分和取值是最显著的部分。结果
要到磁盘上的下一个扇区,我们开始我们的这个增量
的在其至少显著结束。结果
如果通过增加在取值的一部分,我们溢出其范围,我们把它重置为
最小值(1),并开始递增下一更显著一部分
是的 ^ h 在这种情况下。结果
如果通过增加在 ^ h 的一部分,我们溢出其范围,我们把它重置为
最小值(0),并开始递增的最显著一部分
是的 C 在这种情况下。结果
如果通过增加在 C 的一部分,我们溢出其范围,我们把它重置为
最小值(0)。这将使该磁盘上的存储空间。如果输入
正确的SectorCount在这一点上读数被赋予那么通常会有
停了下来。

 ; INPUT:DL =驱动器
; CH =汽缸
; DH =头
; CL =部门
; AX = SectorCount
; ES:BX =缓冲区
;输出:CF = 0 AH = 0
; CH,DH,CL =以下部门CHS
; CF = 1 AH =错误状态
; CH,DH,CL =问题部门CHS
ReadDiskSectors:
  ES推
  推迪
  推基点
  MOV BP,SP;局部变量:
  推斧[BP-2] = SectorCount
  推CX; [BP-4] = MaxSector
  推DX; [BP-6]​​ = MaxHead
  推BX; [BP-8] = MaxCylinder  ES推
  MOV啊,08H
  INT 13H; ReturnDiskDriveParameters
  流行ES
  JC NOK
  MOV BX,CX; 10位缸信息 - > BX
  XCHG BL,BH
  SHR BH,6
  XCHG [BP-8],BX;存储MaxCylinder并获得输入BX回来
  MOVZX DX,DH 8位头信息 - > DX
  XCHG [BP-6,DX;存储MaxHead并获得输入DX回来
  和CX,003FH; 6位的行业资讯 - > CX
  XCHG [BP-4],CX;存储MaxSector并获得输入CX回来ReadNext:
  MOV DI,5;最大5试图每个扇区
ReadAgain:
  MOV AX,0201H;读取扇区
  INT 13H; ReadDiskSectors
  JNC OK
  推斧;在AH保存错误状态字节
  MOV啊,00H
  诠释13H; ResetDiskSystem
  流行斧
  十二月二
  JNZ ReadAgain
  STC
  JMP NOK
好:
  癸字PTR [BP-2]; SectorCount
  JZ就绪
  电话NextCHS
  MOV AX,ES;移动缓冲512字节起来
  加斧,十六分之五百十二
  MOV ES,AX
  JMP ReadNext准备:
  调用NextCHS;返回有用的CHS值支持读取
  XOR啊,啊; - > CF = 0 ...是不是内存不再
NOK:
  MOV SP,BP
  流行基点
  流行迪
  流行ES
  RETNextCHS:
  MOV人,CL;计算6比特扇区号
  和人,00111111b
  CMP人,[BP-4]; MaxSector
  JB NextSector
  CMP DH,[BP-6]​​; MaxHead
  JB NextHead
  MOV AX,CX;计算的10位柱面数
  XCHG人啊
  SHR啊,6
  CMP AX,[BP-8]; MaxCylinder
  JB NextCylinder
DiskWrap:
  MOV CX,1;环绕式在磁盘上的第一个扇区
  MOV DH,0
  RET
NextCylinder:
  INC斧
  SHL啊,6;在CL和CH斯普利特10位柱面数
  XCHG人啊
  MOV CX,AX
  MOV DH,0
  INC CL
  RET
NextHead:
  INC DH
  和Cl,11000000b
NextSector:
  INC CL
  RET

上的扇区大小的说明

虽然这是完全正常的,以具有不在512字节扇区
长度,这是一个假设保存,他们将是大小。
经过几十年的节目我从来没有见过那些没有512字节的任何磁盘
部门。
的结果
如果你坚持要支持不同的尺寸,你可以看看第4个字节
从DI:在DisketteParameterTable为您收到的ES指针
BIOS的功能ReturnDiskDriveParameters。


  

•仿真和直接执行之间如何迭代有什么不同?


我想通过的直接执行的你了解真实的硬件。结果
对于真正的硬件BIOS将返回的几何CHS符号和部门存在的...好只是因为他们是真实的!结果
在仿真模拟器会尽力还为您提供将这些几何值,但是这将是由你来确保有关驱动器上存在足够的部门。这正是@Jester说,当他问你:你甚至有图像文件中的行业通过使用放大图像文件来解决这个问题倍0xFFFF的分贝为0x00

一些额外的建议

您没有设置堆栈。既然你在加载的7C00h处上面的启动扇区你的内核,我建议你初始化SS:SP到0000h:7C00h处的启动扇区下一个堆栈

 主:
  CLI
  异斧,斧
  MOV DS,AX
  MOV ES,AX
  MOV SS,AX
  MOV SP,7C00h处
  STI
  PRINT欢迎

由于@Fifoernik评论你最好把 JMP停止耶DB仁之前,CR,LF NUL 至prevent该数据的执行力!

 内核:
  PRINT耶
  JMP叫停
  耶DB内核,CR,LF NUL

In the process of learning assembly, I am writing an OS. I have successfully written the code necessary for appending a second 512 byte sector to the initial 512 byte bootloader:

%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

I compile the file with: nasm -f bin -o boot.bin boot.asm && qemu boot.bin:

I am curious how heads and cylinders are used:

  • How are the sectors iterated through?
  • How does iteration differ between emulation and direct execution?

解决方案

•How are the sectors iterated through?

To iterate over many sectors using CHS CylinderHeadSector notation, we first have to retrieve the actual limits on these parameters. BIOS has function 08h on int 13h that gives us the maximum values as well as some extra info that we don't need for now.

The sector number in CL ranges from 1 to 63.
The head number in DH ranges from 0 to 255, although 255 is seldom used.
The cylinder number in CL ranges from 0 to 1023. Since this cannot be held in a single byte, the 2 highest bits of this 10-bit number are stored in bits 6 and 7 of the CL register!

How the iteration works

Think of the CHS notation as if it were some kind of number where C is the most significant part and S is the least significant part.
To get to the next sector on the disk we start our incrementation of this number at its least significant end.
If by incrementing the S part we overflow its range, we reset it to its smallest value (1) and start incrementing the next more significant part which is H in this case.
If by incrementing the H part we overflow its range, we reset it to its smallest value (0) and start incrementing the most significant part which is C in this case.
If by incrementing the C part we overflow its range, we reset it to its smallest value (0). This will make for a wraparound on the disk. If on input a correct SectorCount was given then normally at this point reading will have stopped.

; 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

A note on sector size

Although it's perfectly alright to have sectors that are not 512 bytes in length, it's a save assumption that they will be that size. After decades of programming I've never seen any disk that hadn't 512-byte sectors.
If you insisted on supporting different sizes, you can look at the 4th byte of the DisketteParameterTable for which you recieved a pointer in ES:DI from the BIOS function ReturnDiskDriveParameters.

•How does iteration differ between emulation and direct execution?

I suppose that by direct execution you understand real hardware.
For real hardware BIOS will return you the geometry in CHS notation and the sectors exist ... well just because they are real!
Under emulation the emulator will do its best to also provide you will these geometry values but it will be up to you to make sure that enough sectors exist on the concerned drive. This is exactly what @Jester said when he asked you: "Do you even have that sector in the image file?" You resolved this issue by enlarging the image file using times 0xFFFF db 0x00

Some extra advice

You didn't setup the stack. Since you load your kernel above the bootsector at 7C00h, I suggest you initialize SS:SP to 0000h:7C00h for a stack beneath the bootsector.

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

As @Fifoernik commented you would better put the jmp halt before the yay db "kernel", CR, LF, NUL to prevent the execution of this data!

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

这篇关于如何所有的磁盘扇区组装迭代?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆