AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 79544204
Accepted
Ryan Grube
Ryan Grube
Asked: 2025-03-30 13:07:39 +0800 CST2025-03-30 13:07:39 +0800 CST 2025-03-30 13:07:39 +0800 CST

在 16 位实模式下执行 32 位数字乘法以遍历 FAT 表

  • 772

我正在编写一个简单的引导程序(希望很快能编写一个操作系统)。我一直在取得进展,但这部分有点难倒我。

我正在将此操作系统和引导加载程序写入磁盘映像,其中包括:

  1. MBR 引导扇区和第一阶段引导加载程序
  2. 为第二阶段引导加载程序保留 32kb 区域
  3. 一个包含操作系统的 FAT32 分区,以及kernel.bin

我的目标是将 kernel.bin 加载到内存中并跳转到该位置,为了做到这一点,我必须遍历 FAT 表。

读取 FAT32 分区所涉及的许多逻辑需要 32 位值(如许多 BPB 值)

由于我现在基本上处于实模式,因此我不确定在执行乘法等计算时如何处理这些 32 位数字。我知道我可以使用操作数大小前缀和/或地址大小前缀来使用 32 位寄存器,但我无法以有意义的方式对它们进行算术运算。

例子

以下是存储来自 BPB 的重要值的汇编部分:

BPB_info:

    ; BPB info from the FAT32 boot sector
    BPB_NumFATs: db 0 ; Number of FATs (1 byte)
    BPB_FATSz32: dd 0 ; Size of each FAT in sectors (4 bytes)
    BPB_RootClus: dd 0 ; First cluster of the root directory (4 bytes)
    BPB_SecPerClus: db 0 ; Sectors per cluster (1 byte)
    BPB_RsvdSecCnt: dw 0 ; Reserved sectors count (2 bytes)

    ; Calculated values used in the bootloader
    FAT_root_dir_start: dq 0 ; Start of the root directory in sectors (calculated)
    FAT_lba: dq 0 ; Logical block address of the FAT tables (calculated)

为了计算FAT_root_dir_start,我必须使用以下公式:

BPB_RsvdSecCnt + ((BPB_RootClus - 2) * BPB_SecPerClus)

但由于BPB_RootClus是一个双字(32 位),我不确定如何执行此操作。

任何建议都将不胜感激!我走对路了吗?我应该完全不同地处理这个问题吗?也许切换到保护模式?我不确定。

assembly
  • 1 1 个回答
  • 58 Views

1 个回答

  • Voted
  1. Best Answer
    Andrey Turkin
    2025-03-30T13:55:35+08:002025-03-30T13:55:35+08:00

    如果您想坚持使用严格的 x86 指令集,那么您将面临一个典型的长乘法问题(@user207421 指出,在 8086 asm 中将 64 位数字乘以 32 位数字,以获得解释)。在汇编中:

    mov cx, [BPB_RootClus + 2]
    mov ax, [BPB_RootClus]
    sub ax, 2  ; cx:ax = BPB_RootClus - 2 = X; cx = Xh, ax=Xl
    sbb cx, 0
    mov bl, [BPB_SecPerClus] ; bx = y
    mov bh, 0
    mul bx  ; dx:ax = Xl * y
    xchg ax, bx ; dx:bx = Xl * y, ax = y
    mov bp, dx ; bp:bx = Xl * y
    mul cx ; dx:ax = Xh * y
    add ax, bp 
    ; adc dx, 0 - that'd be a carry-over but we'll assume that mutiplication result can fit into 32 bit
    
    ; now X * y is in ax:bx pair, add BPB_RsvdSecCnt
    add bx, [BPB_RsvdSecCnt]
    adc ax, 0
    

    但是如果你可以使用 80386 32 位指令(使用 OPERAND 大小覆盖,而不是地址大小覆盖)那么我认为简单地使用 32 位算术不会有什么问题:

    bits 16
    cpu 386
    ...
    mov eax, [BPB_RootClus]
    sub eax, 2
    movzx edx, byte [BPB_SecPerClus]
    mul edx
    movzx edx, word [BPB_RsvdSecCnt]
    add eax, edx
    
    

    这应该可以编译并正常工作。

    • 3

相关问题

  • x86 - 通过 RETF 从 32 位切换到 64 位

  • 小 ESP32-C3(基于 RISC-V)的浮点汇编指令上无法识别的操作码

  • 如何使用GNU Assembler (GAS)从相应的.s文件创建手写的ELF文件

  • 我无法读取gameboy的LY寄存器

  • 获取Assembly中的参数值

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve