Cómo cargar un kernel desde el disco con el BIOS int 13h en el montaje NASM?
-
20-09-2019 - |
Pregunta
Me han pegado con esto durante semanas y no tienen idea de dónde voy mal porque NASM no me ha dado ningún error. El código es bastante explica por sí mismo debido a los comentarios.
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 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
Solución
jmp [es:bx]
no salta a la dirección de es:bx
. Este comando hace un salto cerca de la dirección almacenada en la palabra de es:bx
. Esta es la razón por un montón de montadores de más edad hacen se escribe 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 ocurrir. 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 desea saltar es:bx
, utilice retf
:
push es
push bx
retf
Otros consejos
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 usted tendrá que hacer explicitamente una llamada / JUMP para ese lugar en particular. El BIOS no llamar a ese código para usted. En el arranque, una vez que se ha inicializado el BIOS, que fijará el IP Instrucción Puntero a la dirección de 0x7C00. La CPU continuación, se iniciará a ejecutar el código secuencial, por lo que sin JMP / CALL para 0x8000 no lo puedo ejecutar el código en 0x8000 hasta que se haya ejecutado todas las direcciones de la memoria entre medio 0x7C00 a 0x8000, etc.
Así que la solución sería tener un JMP o llame a la instrucción después de su readdisk jc.
Si mi entendimiento es incorrecta, me disculpo. Espero que esto ayude.
Uno de gotcha con INT13 es que la cabeza y los números de pista comienzan en 0, pero los números del sector, por alguna razón comienzan en 1. Es posible comprobar que su utilidad sector de la escritura se ajusta a este esquema de numeración.
Preguntas:
- ¿Cuántos puntos es lo que ves cuando arranque?
- ¿El golpe de motor en disquete?
No sé si está utilizando un disquete para arrancar el sistema operativo, pero si usted está usando, le sugiero que usted declare algunas cosas después de la ORG y la declaración Bits, echar un vistazo (que 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.
Saludos.
No estoy seguro de por qué el código no funciona, ya que no puedo comprobar el todo el entorno (disco, volcado de memoria, etc) ... pero lo que puedo decir es ... el código es incorrecto . Que está cargando el segundo programa, no en 0x8000
(que era el punto de utilizar 0rg 0x8000
¿verdad?), Pero al 0x80000
.
La razón es que se utiliza el segmento: desplazamiento de direccionamiento en el camino equivocado,
0x8000:0x0000
la dirección que se resuelva a la dirección de 0x80000
lineal, ya
el valor del segmento se desplaza a la izquierda por 4 bits una después se añadió 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 se espera que también .... eso o va a cargar la sectores erróneos del disco.