Estou escrevendo um bootloader simples (e, espero que em breve, um sistema operacional). Tenho feito progressos, mas esta parte está me deixando um pouco perplexo.
Estou gravando este sistema operacional e bootloader em uma imagem de disco, que consiste em:
- Um setor de inicialização MBR e um bootloader de primeiro estágio
- Uma área reservada de 32kb para o bootloader de segundo estágio
- Uma partição FAT32 que contém o sistema operacional e
kernel.bin
Meu objetivo é carregar kernel.bin na memória e pular para ele, e para fazer isso preciso percorrer as tabelas FAT.
Muita lógica envolvida na leitura da partição FAT32 requer valores de 32 bits (como muitos valores BPB)
Como estou essencialmente bloqueado no modo real por enquanto, não tenho certeza de como lidar com esses números de 32 bits ao executar cálculos como multiplicação. Sei que posso usar registradores de 32 bits usando o prefixo de tamanho do operando e/ou prefixo de tamanho do endereço, mas não posso realmente usar operações aritméticas neles de forma significativa.
Exemplo
Aqui está uma seção do assembly que armazena valores importantes do 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)
Para calcular FAT_root_dir_start
, devo usar a seguinte fórmula:
BPB_RsvdSecCnt + ((BPB_RootClus - 2) * BPB_SecPerClus)
Mas como BPB_RootClus
é uma doubleword (32 bits), não tenho certeza de como realizar essa operação.
Qualquer conselho seria apreciado! Estou no caminho certo? Devo abordar isso de forma completamente diferente? Talvez mudar para o modo protegido? Não tenho certeza.
Se você quiser se ater a um conjunto de instruções x86 estrito, então você está olhando para um típico problema de multiplicação longa ( Multiplicando um número de 64 bits por um número de 32 bits em 8086 asm para uma explicação, conforme apontado por @user207421). Em assembly:
Entretanto, se você estiver de acordo em usar instruções 80386 de 32 bits (usando substituição de tamanho de OPERANDO, mas não uma substituição de tamanho de endereço), então não vejo problema algum em simplesmente usar aritmética de 32 bits:
Isso deve compilar e funcionar perfeitamente.