【问题标题】:What does "invalid command (error code 0x01)" mean within BIOS int 13BIOS int 13 中的“无效命令(错误代码 0x01)”是什么意思
【发布时间】:2021-08-08 23:33:31
【问题描述】:

我正在和我的一个朋友一起开发一个简单的引导加载程序,并没有假装它会变成任何可用的东西。在编写了屏幕输入和输出函数之后,我们继续编写从磁盘读取扇区的函数,这就是第一个问题出现的地方。我声明在 qemu 和 bochs 上一切正常。对于物理硬件我不能说同样的话,我遇到错误 0x0001,这意味着 Invalid Command。

但是,我没有找到有关此错误的太多信息。在我看来,这可能意味着我的某个论点有误,但我在屏幕上打印了所有日志,但没有找到任何奇怪的值来证明这种行为是合理的。

我正在从闪存驱动器启动。我认为这也可能是一个问题(因为它不是真正的软盘),但如果 BIOS 可以加载引导扇区,那么加载下一个扇区也应该没有问题。

但是,这里是 read_sector 函数的代码:

read_sector:
start_f
    pusha
    mov     (drive_number), %dl    # drive number is stored from the main function into a global variable
    mov     $0x03, %si             # try three times

1:
    mov     $0x0201, %ax
    int     $disk_int
    jnc     end

    dec     %si
    jz      2f
    xor     %ah, %ah
    int     $disk_int
    jmp     1b

2:
    movzx   %ah, %dx
    call    printh                 # print error code
end:
    popa
end_f

这里是调用函​​数(dl = 0):

    # ...

    mov     $0x0002, %cx
    xor     %dh, %dh
    mov     $0x7e00, %bx
    call    read_sector

    # ...

我们可能做错了什么?

【问题讨论】:

  • 代码似乎正确。 drive_number 是否正确初始化并正确回读?如果引导加载程序不是太大,你能把它完全贴出来吗?或者制作一个重现问题的精简版本?
  • 当然,代码在github,特别是调用者在init.s,而被调用者在diskout.s。 init 函数将 drive_number 设置为 0x00
  • 尝试移动mov %dl, (drive_number) 在初始化段寄存器:)
  • 天哪,这有道理,我试试
  • 不错!如果您有时间,请考虑使用任何可能帮助面临相同问题的人的信息自行回答您自己的问题。

标签: assembly x86-16 att bios real-mode


【解决方案1】:

这里的问题在于文件init.s。在初始化代码段之前,我在drive_number 中输入了一个值。

CPU如何计算物理地址

real mode memory segmentation.

当我将此列表翻译成机器语言时,链接器通过引用它所在节的开头来计算drive_number 的地址(在本例中为.text 节,它从地址7c00 开始,如链接描述文件中所指定):

.text 0x7c00 :
    {
        *(.text);
    }

这意味着指令mov $0, (drive_number) 被翻译成mov $0, 7c2e。然而,这不是一个实际的物理地址,而只是一个偏移量。 在实模式下,物理地址是通过将特定段寄存器中移位 4 位(与乘以 16)的值相加到偏移量(在本例中为 7c2e)来计算的.我们经常看到AAAA:BBBB 表示地址AAAA * 16 + BBBB。为了确定内存中用于读取或写入某种数据的位置的物理地址,CPU 默认利用存储在数据段寄存器%ds 中的值。这意味着我们存储数据的实际地址确实是ds * 16 + drive_number。

当 BIOS 跳转到写入引导扇区的代码时,它并不能保证段寄存器中的值是我们想要的值。因此,在每个程序开始时,我们必须初始化这些寄存器以包含我们需要的值。如果%ds不为零,则drive_number对应的物理地址在%ds初始化为零后就不一样了,这意味着这个标签根据包含的值指向内存中的不同位置在%ds.

BIOS 告诉我们从哪个驱动器启动

BIOS 中断13, 2 要求 dl 包含指示我们应该从哪个驱动器读取的代码。然而,从我们引导的驱动器中读取文本不需要在手动之后查阅手册:事实上,BIOS 将与我们引导的驱动器对应的值放在%dl 中,然后跳转到07c0:0000 并开始执行引导扇区中的代码。 使用%dl中的BIOS传递的代码,使代码更加可靠和健壮。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-18
    • 1970-01-01
    • 2012-10-01
    • 2015-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多