Int 13H AH=00h 的具体和有用的例子

Concrete and useful example of Int 13H AH=00h

提问人:Bastien Portigo 提问时间:11/13/2023 最后编辑:Michael PetchBastien Portigo 更新时间:11/16/2023 访问量:174

问:

我能举一个具体而有用的例子吗?在以 16 位模式运行的处理器上用 nasm 编码的示例,以便我在实践中能够理解,必须对代码产生影响,如果我删除它会导致错误或更改。Int 13H AH=00hInt 13H AH=00h

我在 virtualbox 上使用 img 软盘,我在引导扇区。

我明白了这个理论:RESET DISK SYSTEM 强制控制器重新校准驱动器磁头(寻求跟踪 0)。Int 13H AH=00h

我想比理论走得更远,并通过实际使用的示例代码来理解。Int 13H AH=00h

我正在遵循的教程使用,但它对代码没有影响,它没有用,相反,我需要一个真正有用和影响的实际示例Int 13H AH=00hInt 13H AH=00h

组装 VirtualBox Interrupt x86-16 BIOS

评论

0赞 Nassau 11/13/2023
stackoverflow.com/questions/77416720/......
0赞 Bastien Portigo 11/13/2023
此链接上没有具体且有用的示例
0赞 ecm 11/13/2023
据说某些单元,特别是软盘驱动器,可能不可靠,需要多次读取请求,直到其中一个成功。这就是为什么加载程序通常会重试读取请求几次的原因。在两次尝试之间使用 int 13h service 00h 调用“重置”设备是帮助驱动器最终成功的最佳实践。然而,在现代或虚拟系统上,它可能是多余的。
0赞 Bastien Portigo 11/14/2023
2)您个人是否曾经遇到过BIOS错误。ReadDiskSector 函数 02h 或 BIOS。WriteDiskSector 函数 03h 强制您使用 Int 13H AH=00h,并且在不重置的情况下无法解决?也许 13H AH=00h 在虚拟机上没有用,它只对真正的软盘有影响?
2赞 Peter Cordes 11/15/2023
也许 13H AH=00h 在虚拟机上没有用 - 我希望这是真的!软件不会偏离对齐并需要重新校准,除非它故意模拟不完美的硬件!

答:

1赞 Nassau 11/13/2023 #1

好吧,例如,这是 qemu mbr 代码。检查之间的部分。******

di = 5是尝试从磁盘读取的次数。因此,如果发生错误,代码会递减,经过 5 次尝试,我们会在下一步代码中生成消息。CF = 1didi = 0"Error loading operating system"

+       fa                  cli                         ; clear IF
+       33 c0               xor ax,ax                   ; ax = 0000
+       8e d0               mov ss,ax                   ; ss = 0000
+       bc 00 7c            mov sp,7c00                 ; sp = 7c00     
+       8b f4               mov si,sp                   ; si = 7c00
+       50                  push ax                     ; ↑ ax = 0000
+       07                  pop es                      ; ↓ es = 0000
+       50                  push ax                     ; ↑ ax = 0000
+       1f                  pop ds                      ; ↓ ds = 0000   
+       fb                  sti                         ; set IF
+       fc                  cld                         ; clear DF
        
        // copy 512 bytes (2 * 256), ds:si [0000:7c00] -> es:di [0000:0600]
        
+       bf 00 06            mov di,0600                 ; di = 0600
+       b9 00 01            mov cx,0100                 ; cx = 0100(256)
+       f2                  repnz                       ; if != 0
+       a5                  movsw                       ; copy 256 words
+       ea 1d 06 00 00      jmp 0000:061d                   
        
+       be be 07            mov si,07be                 ; partition table offset
        
+       b3 04               mov bl,04                   ; 4 entries
+3      80 3c 80            cmp byte ptr [si],80        ; 80 = active partiton
+1>     74 0e               jz +14                      ; 80 found
+       80 3c 00            cmp byte ptr [si],00        ; no entry      
+2>     75 1c               jnz +28                     ; other system
+       83 c6 10            add si,+10                  ; check next entry
+       fe cb               dec bl                      ; dec number of records     
+3>     75 ef               jnz -17                     ; if nothing found, check again, next record
    
+       cd 18               int 18                      ; rom bios
        
        // read from partition table record
        
+1      8b 14               mov dx,[si]                 ; [07be] = dh(head) = 01 dl(drive number) = 80 
+       8b 4c 02            mov cx,[si + 02]            ; [07c0] = ch(cylinder) = 00 cl(sector number ) = 01 
+       8b ee               mov bp,si                   ; bp = 07be, first partition table entry
+5      83 c6 10            add si,+10                  ; move to next record
+       fe cb               dec bl                      ; dec number of records     
+4>     74 1a               jz +26                      ; no more records, read sector
+       80 3c 00            cmp byte ptr [si],00        ; no entry? check next or show "invalid partition table"
+5>     74 f4               jz -12                      ; 1111 0100 , 0000 1011, 0000 1100, -0c
        
+2      be 8b 06            mov si,068b                 ; "invalid partition table"
+7,9,11 ac                  lodsb                       ; al = ds:si
+       3c 00               cmp al,00                   ; end of string?
+6>     74 0b               jz +11                      ; go infinity loop
+       56                  push si                     ; ↑ si = 07fe, offset 55 AA
+       bb 07 00            mov bx,0007                 ; 
+       b4 0e               mov ah,0e                   ; tty show char
+       cd 10               int 10                      ; graphics int  
        
+       5e                  pop si                      ; ↓ si = 07fe, 55 aa
+7>     eb f0               jmp -16                     ; load next char, 1111 0000, 0000 1111, 0001 0000, -16
+6>     eb fe               jmp -2                      ; infinity loop, stop working
*********************************************************       
+4      bf 05 00            mov di,0005                 ; di = 0005, if disk error, we have 5 tries
+10     bb 00 7c            mov bx,7c00                 ; buffer, es:bx = 0000:7c00
+       b8 01 02            mov ax,0201                 ; ah = 02 read, al = 01 1 sector
+       57                  push di                     ; ↑ di = 0005
+       cd 13               int 13h                     ; disk int
        
+       5f                  pop di                      ; ↓ di = 0005
+8>     73 0c               jnb +12                     ; no errors?
+       33 c0               xor ax,ax                   ; error, ax = 0000, reset disk system
+       cd 13               int 13h                     ; disk int  

+       4f                  dec di                      ; decrement number of tries 
+10>    75 ed               jnz -19                     ; if not 0, try again, 1110 1101, 0001 0011, -19
+       be a3 06            mov si,06a3                 ; si = offset "Error loading operating system" 
+11>    eb d3               jmp -45                     ; go lodsb, 1101 0011, 0010 1101, -45
*********************************************************
+8      be c2 06            mov si, 06c2                ; si = offset "Missing operating system"
+       bf fe 7d            mov di,7dfe                 ; di = offset 55 AA
        
+       81 3d 55 aa         cmp word ptr [di],aa55      ; [di] == 55 aa?
+9>     75 c7               jnz -57                     ; go lodsb, 1100 0111, 0011 1001, -57
+       8b f5               mov si,bp                   ; si = 07be, first partition table entry 
+       ea 00 7c 00 00      jmp 0000:7c00               ; jmp to new loaded data

评论

0赞 Bastien Portigo 11/14/2023
当我删除 Int 13H AH=00h 时,它不会更改代码中的任何内容,它对您的示例没有影响,也许 13H AH=00h 在虚拟机上没有用,它只对真正的软盘有影响?
0赞 Nassau 11/15/2023
我认为程序应该考虑所有可能的结果,并通知用户硬件有问题。如果 hdd 开始行为不端怎么办?我不知道发生这种情况的可能性有多大,但最好有针对这种情况有一些保护的代码。
0赞 Bastien Portigo 11/15/2023
您个人是否曾经遇到过BIOS错误。ReadDiskSector 函数 02h 或 BIOS。WriteDiskSector 函数 03h 强制您使用 Int 13H AH=00h,并且在不重置的情况下无法解决?
0赞 Bastien Portigo 11/15/2023 #2

正如本文档所述,Int 13H AH=00h 在像 VirtualBox 这样的虚拟机上是无用的

如果稍后在 VM 外部使用 Int 13H AH=00h,则保留它是相关的。

不可能有一个具体且有用的示例对虚拟机上的 Int 13H AH=00h 代码产生实际影响。谷歌、stackoverflow、chatgpt 上没有工作示例

随着 SSD 驱动器的出现,该功能不再真正有任何用途,尤其是因为 int 0x13 不再用于使用 UEFI 的现代操作系统,其中真实模式 BIOS 功能仍然存在以实现向后兼容性。

评论

2赞 Michael Petch 11/16/2023
这里存档了 IBM-PC ROM BIOS 的官方 IBM 文档:bitsavers.trailing-edge.com/pdf/ibm/pc/ps2/... (磁盘重置 int 13h/ah=2 被记录在案。虚拟机没有像真实软盘那样的机械部件,因此磁盘重置可能没有可观察到的效果,并且虚拟设备上不可能出现某些类型的错误。
1赞 Michael Petch 11/16/2023
至于一个具体的例子,我们总是可以看看 MS-DOS 的引导扇区,一直追溯到 2.00。在该原始引导扇区中,卷引导记录被链接,并在该代码中调用 int 13h/ah=2,如果设置了进位标志,则执行磁盘重置 (int 13h/ah=0) 并重试(最多 5 次)。有人在这里拆解了 MS-DOS 2.00 引导加载程序: thestarman.pcministry.com/asm/mbr/200MBR.htm .搜索,这就是我所指的代码。065E BF0500
0赞 Michael Petch 11/16/2023
在好日子里(80 年代后期),软盘上的磁盘错误非常普遍,尤其是在边缘廉价磁盘上。
0赞 Michael Petch 11/16/2023
在我的第一条评论中,“磁盘重置 int 13h/ah=2 已记录”应该是“磁盘重置 int 13h/ah=0 已记录”
1赞 Michael Petch 11/16/2023
我只能用这个说明来结束:如果你编写的代码使用 int 13h 进行读/写等,并且你从不使用 int 13/ah=0,你的代码可能总是在虚拟机上工作,并且它可能会在实际硬件上的大多数媒体上工作。如果你在上一代真正的软盘机械硬件上尝试它(使用廉价的磁盘介质),那么你可能会发现你的代码的弹性不如在检测到错误时重试磁盘操作并重置的代码。