Загрузочное ядро x86 из отдельного kernel.asm (nasm)
Я написал бутстрап для загрузочного сектора. Этот загрузчик пытается загрузить ядро из этапа 2 во втором секторе.
Если я включаю ядро в тот же asm, все работает как положено. если я добавлю файл kernel.bin из kernel.asm со смещением 512 байт в образ диска, он не будет делать то же самое, даже с точно таким же кодом. Вместо этого это печатает jibberish.
Мой код для чтения второго сектора и его выполнения выглядит следующим образом...
read_first_byte:
pusha
mov ah, 0 ; reset disk
mov dl, [boot_drive] ; drive 0
stc
int 13h
jc rs_fail ; return, we're a failure
reset_success:
mov bx, stage2 ; place in memory 512 bytes past where the MBR is loaded.
mov ah, 0x02 ; function
mov al, 0x01 ; sectors to read
mov ch, 0x00 ; track/cyl
mov cl, 0x02 ; sector start
mov dh, 0x00 ; head
mov dl, [boot_drive] ; drive
print_hex [boot_drive]
stc
int 13h
jc rs_fail
print_hex [stage2]
print_hex [stage2 + 1]
jmp stage2
;jmp disk_return
rs_fail:
call int13_show_error
;; mov ds, es
;; mov si, 512 ; prep lodsb
;; lodsb ; load the first byte of the disk sector read - sector 2
disk_return:
popa
ret
Конец 512 по разделам...
buffer times 510-($-$$) db 0 ; Pad remainder of boot sector with 0s
dw 0xAA55 ; The standard PC boot signature
stage2:
mov si, text_string ; Put string position into SI
call print_string ; Call our string-printing routine
mov si, crlf ; Put string position into SI
call print_string ; Call our string-printing routine
call read_keys
jmp $
print_key:
mov ah, 0 ; 16h read key function
int 16h ; al now has character from keyboard
mov ah, 0Eh ; TTY output, ah had scan code, we discard
int 10h ; prints character in ah
read_keys:
mov ah, 01h ; detect key
int 16h
jnz print_key ; only print if key in buffer
jmp read_keys ; Jump to read_keys - infinite loop!
text_string db 'Kernel loaded!', 0
buffer2 times 1024-($-$$) db 0
Файл kernel.asm выглядит следующим образом...
BITS 16
start:
mov si, text_string ; Put string position into SI
call print_string ; Call our string-printing routine
mov si, crlf ; Put string position into SI
call print_string ; Call our string-printing routine
call read_keys
jmp $
print_key:
mov ah, 0 ; 16h read key function
int 16h ; al now has character from keyboard
mov ah, 0Eh ; TTY output, ah had scan code, we discard
int 10h ; prints character in ah
read_keys:
mov ah, 01h ; detect key
int 16h
jnz print_key ; only print if key in buffer
jmp read_keys ; Jump to read_keys - infinite loop!
print_string: ; Routine: output string in SI to screen
push ax
mov ah, 0Eh ; int 10h 'print char' function
.repeat:
lodsb ; Get character from string
cmp al, 0
je .done ; If char is zero, end of string
int 10h ; Otherwise, print it
jmp .repeat
.done:
pop ax
ret
crlf db 0x0a,0x0d,0
text_string db 'Kernel loaded!', 0
И загрузчик, и ядро собраны со следующим, на случай, если я захочу использовать gdb...
nasm -f elf -g -o file.elf file.asm
objcopy -O binary file.elf file.bin
Для рабочего примера, у меня есть моя маленькая ОС на github. В ветке "kernel" я собираю ядро из отдельного файла kernel.asm. Конкретный момент времени находится по адресу https://github.com/TrentonAdams/tinyos/tree/0524a1af9de7b3e58c7e2c0660f587d4c8573e98
make clean test # runs qemu with the single myfirst.asm code
make clean kernel # runs qemu with a disk image that has the kernel.bin in the second sector.
Для того, чтобы этот переполнение стека оставалось отдельным постом, не требующим внешних ссылок, пожалуйста, дайте мне знать, достаточно ли содержания поста для ответа на вопрос. то есть, если вам действительно нужно было узнать что-то от github, чего не было в этом посте, дайте мне знать, и я могу обновить это.
1 ответ
У вас несоответствие фактического ds
и предположил org
, Исправьте любой из них, чтобы они соответствовали. Если вы не использовали org
в файле он по умолчанию равен нулю, поэтому вам нужно настроить ds
так что он указывает на адрес загрузки, например mov ax, 0x7e0; mov ds, ax
перед передачей управления на второй сектор. В качестве альтернативы используйте правильное org
например, org 0x200
сказать ассемблеру, что это продолжение первого сектора.