Как загрузить ядро ​​с диска с BIOS int 13h в сборке NASM? - PullRequest
10 голосов
/ 11 октября 2009

Я застрял с этим уже несколько недель и понятия не имею, где я иду не так, потому что NASM не дал мне никаких ошибок. Код довольно понятен из-за комментариев.

это код, который загружается из BIOS

 ;--------------------------------------------
 ; 'boot.asm'
 ; loaded from BIOS

 [org 0x7C00]
 [bits 16]

 ;--------------------------------------------

 main:
  mov ah, 0x0E  ; print function
  mov al, '.'   ; ascii char
  int 0x10   ; IO int

 resetdisk:
  mov ah, 0x00  ; reset function
  mov dl, 0x00  ; drive
  int 0x13   ; disk int
  jc resetdisk

 readdisk:
  mov bx, 0x8000  ; segment
  mov es, bx
  mov bx, 0x0000  ; offset

  mov ah, 0x02  ; read function
  mov al, 0x03  ; sectors
  mov ch, 0x00  ; cylinder
  mov cl, 0x02  ; sector
  mov dh, 0x00  ; head
  mov dl, 0x00  ; drive
  int 0x13   ; disk int
  jc readdisk
  jmp [es:bx]   ; buffer

 ;--------------------------------------------

 times 510 - ($ - $$) db 0x00
 db 0x55, 0xAA

Это код, который должен быть загружен (но не загружен)

 ;--------------------------------------------
 ; 'load.asm'
 ; loaded from 'boot.asm'

 [org 0x8000]
 [bits 16]

 ;--------------------------------------------

 main:
  mov ah, 0x0E  ; print function
  mov al, '.'   ; ascii char
  int 0x10   ; IO int

  jmp $    ; hang

Любая помощь будет принята с благодарностью.

Patrick

Ответы [ 5 ]

7 голосов
/ 13 октября 2009

jmp [es:bx] не переходит на адрес es:bx. Эта команда выполняет быстрый переход к адресу, указанному в слове в es:bx. Вот почему многие старые ассемблеры заставляли вас писать такие инструкции как jmp word ptr [es:bx] или даже jmp near ptr [es:bx]; так будет яснее, что произойдет. То, что вы, вероятно, хотите здесь, это далеко прыгнуть в фиксированное место:

; jmp far 8000:0000
db 0eah
dw 00000h ; offset
dw 08000h ; segment

Если вы хотите перейти на es:bx, используйте retf:

push es
push bx
retf
2 голосов
/ 13 октября 2009

Одна хитрость с INT13 состоит в том, что номера заголовков и дорожек начинаются с 0, а номера секторов по какой-то причине начинаются с 1. Вы можете проверить, соответствует ли ваша утилита записи секторов этой схеме нумерации.

Вопросы:

  • Сколько точек вы видите при загрузке?
  • Включается ли дисковод?
2 голосов
/ 11 октября 2009

Я не уверен, что вы пытаетесь достичь с помощью кода, но если я правильно понимаю, вы хотите прочитать несколько секторов с диска в папку 0x8000 и затем выполнить этот код?

Если это так, то вам придется явно сделать CALL / JUMP в этом конкретном месте. BIOS не будет вызывать этот код для вас. При загрузке, после инициализации BIOS, IP-адрес указателя будет установлен на адрес 0x7c00. Затем процессор начнет последовательно выполнять код, поэтому без JMP / CALL до 0x8000 он не будет выполнять код с 0x8000, пока не выполнит каждый адрес памяти в диапазоне от 0x7c00 до 0x8000 и т. Д.

Таким образом, решение будет иметь инструкцию jmp или call после вашего jc readdisk.

Если мое понимание неверно, тогда я прошу прощения. Надеюсь, это поможет.

1 голос
/ 12 октября 2009

Я не знаю, используете ли вы дискету для загрузки своей ОС, но если вы используете, я предлагаю вам объявить некоторые вещи после объявления ORG и Bits, посмотрите (они очень важны):

JMP short main   ; Jump past disk description section
NOP              ; Pad out before disk description

; ------------------------------------------------------------------
; Disk description table, to make it a valid floppy
; Note: some of these values are hard-coded in the source!
; Values are those used by IBM for 1.44 MB, 3.5 diskette

OEMLabel            db "BERL OS"    ; Disk label - 8 chars
BytesPerSector      dw 512          ; Bytes per sector
SectorsPerCluster   db 1            ; Sectors per cluster
ReservedForBoot     dw 1            ; Reserved sectors for boot record
NumberOfFats        db 2            ; Number of copies of the FAT
RootDirEntries      dw 224          ; Number of entries in root dir
LogicalSectors      dw 2880         ; Number of logical sectors
MediumByte          db 0F0h         ; Medium descriptor byte
SectorsPerFat       dw 9            ; Sectors per FAT
SectorsPerTrack     dw 18           ; Sectors per track (36/cylinder)
Sides               dw 2            ; Number of sides/heads
HiddenSectors       dd 0            ; Number of hidden sectors
LargeSectors        dd 0            ; Number of LBA sectors
DriveNo             dw 0            ; Drive No: 0
Signature           db 41           ; Drive signature: 41 for floppy
VolumeID            dd 00000000h    ; Volume ID: any number
VolumeLabel         db "BERL OS"    ; Volume Label: any 11 chars
FileSystem          db "FAT12"      ; File system type: don't change!

; End of the disk description table
; ------------------------------------------------------------------

Хорошая идея это поставить.

С уважением.

0 голосов
/ 30 апреля 2011

Я не уверен, почему код не работает, так как я не могу проверить всю среду (диск, дамп памяти и т. Д.) ... но я могу сказать, что ... код неправильный , Вы загружаете вторую программу не в 0x8000 (это был смысл использования 0rg 0x8000, верно?), А в 0x80000.

Причина в том, что вы используете сегмент: неправильная адресация смещения, адрес 0x8000:0x0000 разрешается в линейный адрес 0x80000, так как значение сегмента сдвигается влево на 4 бита и затем добавляется к смещению.

Чтобы решить эту проблему, вы должны взглянуть на дамп памяти и посмотреть, программа работает так, как вы ожидаете, тоже .... либо это, либо вы загружаете неправильные сектора диска.

...