2009-10-11 14 views
9

He estado atascado con esto durante semanas y no tengo idea de dónde me estoy equivocando porque NASM no me ha dado ningún error. El código es bastante auto explicativo debido a los comentarios.Cómo cargar un kernel desde el disco con el BIOS int 13h en el ensamblado NASM?

este es el código que se carga desde la 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 

Este es el código que debe ser (pero no lo es) cargado

;-------------------------------------------- 
; '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 

Cualquier ayuda sería muy apreciada .

Patrick

+0

Por favor, corrija si me equivoco, pero tal vez será un mejor enfoque si en lugar de 'jmp $' usted hace 'cli' para borrar las interrupciones seguidas por' hlt' para detener la CPU. De esta forma evitará consumir mucho tiempo de CPU. – kaneda

+0

Minimal ejemplo gas de trabajo: https://github.com/cirosantilli/x86-bare-metal-examples/blob/1f6af9021283dc01f2247efbb6aa9217363fbf07/bios_disk_load.S –

Respuesta

7

jmp [es:bx] no se escapa a la dirección es:bx. Este comando da un salto cercano a la dirección almacenada en la palabra al es:bx. Esta es la razón por la cual muchos ensambladores más antiguos te hicieron deletrear este tipo de instrucción como jmp word ptr [es:bx] o incluso jmp near ptr [es:bx]; es más claro de esta manera lo que va a suceder.Lo que probablemente quiere aquí es un salto muy lejos a un lugar fijo:

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

Si usted quiere saltar a es:bx, utilice retf:

push es 
push bx 
retf 
+0

Parece lo correcto, pero no puedo hacer que funcione. Cualquier enlace a tutoriales/documentos? –

+0

No: S, esto funciona. Solo usé un '.img' en vez de 'a:'. Tendré que cambiar eso. –

+2

¿Por qué no simplemente hacer directamente "jmp 0x0000: 0x8000" en nasm? Es más legible – SecurityMatt

2

No estoy seguro de lo que está tratando de lograr con el código, pero si he entendido bien, que desea leer unos pocos sectores del disco en la ubicación 0x8000 y luego ejecutar ese código?

Si ese es el caso, entonces tendrá que hacer una LLAMADA/SALTO explícitamente a esa ubicación en particular. El BIOS no llamará ese código por ti. En el arranque, una vez que se inicializa el BIOS, configurará el IP del puntero de instrucción en la dirección 0x7c00. La CPU comenzará a ejecutar el código secuencialmente, por lo que sin JMP/CALL a 0x8000 no ejecutará el código a 0x8000 hasta que haya ejecutado cada dirección de memoria entre 0x7c00 a 0x8000, etc.

Entonces la solución sería tener una instrucción jmp o call después de tu jc readdisk.

Si mi comprensión es incorrecta, entonces me disculpo. Espero que esto ayude.

+0

la JMP es después de la readdisk jc: JMP [ES: bx] donde es : bx es el buffer del código –

+0

Lamento haberme perdido ese. Solo una cosa, mirando tu código. ¿Estás seguro de que tu archivo load.asm está en el sector 2? –

+0

sí, uso dd para win32 y está en el sector después del arranque –

1

No sé si está utilizando un disquete para iniciar su sistema operativo, pero si está utilizando, le sugiero que declare algunas cosas después de la declaración ORG y Bits, eche un vistazo (son muy importantes) :

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 
; ------------------------------------------------------------------ 

Es una buena idea poner esto.

Atentamente.

+0

esto realmente no importa. Es para los sistemas de archivos y el BIOS –

+0

Ok, ahora sé la idea principal. Saludos –

2

Uno de los problemas con INT13 es que los números de cabeza y de pista comienzan en 0, pero los números de sector comienzan por 1. Puede verificar que su utilidad de escritura de sectores cumpla con este esquema de numeración.

Preguntas:

  • ¿Cuántos puntos es lo que ves cuando arranque?
  • ¿Se activa el motor de disquete?
+0

Sí, lo he comprobado y no es eso. Además, uso un emulador (win32 qemu) para que el floppy no se active. –

0

No estoy seguro de por qué el código doesn' t trabajo, ya que no puedo verificar todo el entorno (disco, volcado de memoria, etc.) ... pero lo que puedo decir es ... que el código es incorrecto. Está cargando el segundo programa, no al 0x8000 (ese fue el punto de usar 0rg 0x8000 ¿verdad?), Pero al 0x80000.

La razón es que se utiliza el segmento: desplazamiento de direccionamiento en el camino equivocado, la dirección de 0x8000:0x0000 se resuelve a la dirección lineal 0x80000, ya el valor del segmento se desplaza a la izquierda 4 bits de una añadió a continuación a la compensación .

Para resolver este problema, debería echar un vistazo a un volcado de memoria y ver si el programa funciona como usted espera también ... o eso o está cargando los sectores incorrectos del disco.

Cuestiones relacionadas