Запутался в сегментации X86 - PullRequest
3 голосов
/ 07 февраля 2020

Я пишу загрузочный сектор для загрузки моего 16-битного клона DOS реального режима, и я застрял на чем-то, что может быть совершенно очевидно, но я потратил часы времени, пытаясь понять, почему это не сработает .

В основном я пытаюсь установить DS, CS, SS на ноль, но держу ES установленным прямо после 7C00 для загрузки системы.

Но при запуске моего кода через отладчик он говорит, что ничего не было прочитано в память, то есть: root, FATs и т. д. c (???)

По сути, я пытаюсь сравнить DS:SI (0000: 7C00 + ФАЙЛ) ДО ES:DI (07E0: 0000), но безрезультатно. Я слышал, кто-то сказал мне, что на самом деле он проверяет DS:SI с DS:DI, и поэтому я попробовал, но это тоже не сработало. Не должно ли 07E0: 0000 быть сразу после 0000: 7C00? cmpsb требует, чтобы ES & DS были одинаковыми?

Я смотрел в руководствах Intel, но там говорится, что cmpsb сравнивает DS:SI с ES:DI, но я не думай, что я слишком неправильно понимаю. 07E0: 0000 - это 0x7E00, нет?

В любом случае, спасибо за любую помощь. Я ценю это.

РЕДАКТИРОВАТЬ: я забыл упомянуть, что если я обнуляю ES и помещаю адрес загрузки в BX, все работает. Но когда это перевернуто, ES=07E0, BX=0, ничего не работает или даже не читается. Не знаю почему, поскольку ES:BX должно быть одинаковым независимо от того, по какому маршруту вы идете.

Мой код:

ORG 7C00H
    USE16

BPBBEG:
    JMP  SHORT BPBPEND
    NOP

        DB "PEDOS1.0"
BYTSPERSEC: DW 512      ; total bytes per sector on this volume
SECPERCLUS: DB 1        ; total sectors per cluster on this volume
RSVDSECCNT: DW 1        ; unused
NUMFATS:    DB 2        ; total FATs on this volume
ROOTENTCNT: DW 224      ; total entries in the Root Directory
        DW 80 * 36
        DB 240
FATSZ16:    DW 9        ; total sectors per FAT on this volume
SECPERTRK:  DW 18       ; total sectors per track on this idks
NUMHEADS:   DW 2        ; total heads per cyliner on this idks
        DD 0
        DD 0
        DB 0
        DB 0
        DB 41
        DD 0
        DB "           "
        DB "FAT12   "
;
; PEDOS MEMORY MAP
;
;   -  --  ROM / VIDEO  -- A000:0
;   -   -----------------
;   -  --  BIOS DATA    -- 8000:0
;   -   -----------------
;   -  --  FREE         -- ????:?
;   -   -----------------
;   -  --  BOOT / FREE  -- 0000:7C00
;   -   -----------------
;   -  --  FREE         -- ????:?
;   -   -----------------
;   -  --  DRIVERS      -- ????:?
;   -   -----------------
;   -  --  SYSTEM       -- 0050:0
;   -   -----------------
;   -  --  BIOS BATA    -- 0000:400
;   -   -----------------
;   -  --  IVT          -- 0000:0
;

;
; INITIALIZE SEGMENT REGISTERS
;
BPBPEND:
    XOR  AX, AX
    MOV  DS, AX
    CLI
    PUSH DS
    POP  SS
    MOV  SP, 7C00H
    PUSH DS
    PUSH CHKDSK
    STI
    RETF    ; SET CS TO KNOWN VALUE
;
; LOAD ROOT DIRECTORY AND CHECK FOR
; SYSTEM FILE
;
CHKDSK:
    MOV  AX, WORD BUFFER
    SHR  AX, 4
    MOV  ES, AX ; ES = 07E0
    XOR  AX, AX
    MOV  AX, WORD [FATSZ16]
    MUL  WORD [NUMFATS]
    ADD  AL, BYTE [RSVDSECCNT]
    ;mov  bx, 0x7e00
    MOV  DI, 1
    CALL READSEC


;   mov  ah, 14
;   mov  al, '/'
;   int  16
;   jmp  $

    LEA  SI, [FILE] ; ADDRESS OF FILENAME
    MOV  DI, 0
    MOV  CX, 11     ; 11 BYTES PER FAT FILENAME
    CLD
    REPZ CMPSB
    JZ   LOADFILE
    JMP  ERROR

; DOSBIOS.SYS CONFIRMED: LOAD THE
; FILE INTO MEMORY.

LOADFILE:
    mov  ah, 14
    mov  al, '.'
    int  16
    jmp  $

    MOV  AX, 32
    MOV  BX, WORD [ROOTENTCNT]  ; TOTAL FATS ON DISK
    MUL  BX
    MOV  BX, WORD [BYTSPERSEC]  ; FAT SIZE IN SECTORS
    DIV  BX
    ;
    ; AX = SIZE OF ROOT DIRECTORY
    ;   IN SECTORS
    ;
    ADD  AX, BP ; SIZE + LOCATION = DATA REGION
    POP  BX
    PUSH BX
    MOV  DI, 1  ; DOS SIZE IS HARD CODED FOR NOW - MAY
    CALL READSEC    ; CHANGE IN THE FUTURE
RUNDOS:
    POP  BX
    PUSH 0
    PUSH BX
    RETF
;
; READ THE SPECIFIED SECTORS INTO MEMORY
; AT LOGICAL ES:BX      
;
; IN:   DX:AX   = HEAD, TRACK, SECTOR NUMBER
;   DI  = SECTOR COUNT
;
READSEC:
    PUSHA
    DIV  WORD [SECPERTRK]
    ;
    ; AX = LBA / SECPERTRACK
    ; DX = LBA % SECPERTRACK
    ;
    MOV  CX, DX
    INC  CX     ; CX = LBA 1
    XOR  DX, DX
    DIV  WORD [NUMHEADS]
    ;
    ; AX = (LBA / SECPERTRACK) / CYLHEADCNT = CYLINDER
    ; DX = (LBA / SECPERTRACK) % CYLHEADCNT = HEAD
    ;
    MOV  CH, AL
    SHL  AH, 6
    OR   CL, AH
    MOV  DH, DL
    MOV  DL, 0
    ;
    ; DH = HEAD HUMBER
    ; DL = DRIVE
    ;
    MOV  AH, 2
    MOV  AL, 1
    INT  19
    JNC  NEXTSEC    ; IN CASE OF ERRORS, FOLLOW
ERROR:
    LEA  SI, [ERRMSG]   ; SOMETHING WENT WRONG, SO THROW AN ERROR
;
; WRITE SPECIFIED STRING TO VIDEO
; MEMORY
;
; DS:SI = ADDRESS OF STRING
;
PRINT:
    LODSB
    OR   AL, 0
    JZ   HALT
    MOV  AH, 14
    MOV  BX, 7
    INT  16
    JMP  PRINT
HALT:
    MOV AX, 0
    INT 22
    INT 25
;
; CONTINUE 'READSEC'
;
NEXTSEC:
    POPA
    DEC  DI
    JZ   RETURN ; SKIP PRINT SUBROUTINE
    ADD  BX, WORD [BYTSPERSEC]
    ADD  AX, 1
    ADC  DX, 0
    JMP  READSEC
RETURN:
    RET
;
; KEEP DATA BELOW CODE, UNTIL SECTOR
; MARKER
;
ERRMSG: DB 10, "Disk Error or DOSBIOS.SYS is missing.", 13
    DB 10, "Press any key to restart.", 13, 10, 10, 0
FILE:   DB "DOSBIOS SYS"

    TIMES (512 - 2) - ($ - $$) DB 0

MARKER: DW 0AA55H
BUFFER:
;
; THE SYSTEM IS LOADED DIRECTLY AFTER
; BOOTSTRAP
;

1 Ответ

4 голосов
/ 08 февраля 2020

Проверьте свои размеры!

С одной стороны вы определяете:

RSVDSECCNT: DW 1        ; unused
NUMFATS:    DB 2        ; total FATs on this volume
ROOTENTCNT: DW 224      ; total entries in the Root Directory

С другой стороны вы рассчитываете:

MOV  AX, WORD [FATSZ16]
MUL  WORD [NUMFATS]
ADD  AL, BYTE [RSVDSECCNT]
  1. Ассемблер закодирует то, что вы просили, и умножит AX на слово NUMFATS, которое включает использование старшего байта мусора (в данном случае значение 224)!
  2. Вам не сойдет с ошибочно добавленного RSVDSECCNT, потому что эти цифры очень малы - по крайней мере, если первая проблема исправлена! Но так как это определено как слово, которое вы действительно должны написать add ax, [RSVDSECCNT].

Решение:

MOVZX AX, BYTE [NUMFATS]
MUL   AX, WORD [FATSZ16]
ADD   AX, WORD [RSVDSECCNT]

Указатель входит в ES:BX

CHKDSK:
    MOV  AX, WORD BUFFER
    SHR  AX, 4
    MOV  ES, AX ; ES = 07E0
    XOR  AX, AX

Измените это XOR AX, AX на XOR BX, BX

...