我在创建操作系统时遇到问题。 我有 2 个文件(bootloader.s && kernel.s) 但是当我编译这两个文件并执行时
as -o bootloader.o bootloader.s
ld -o bootloader.bin --oformat binary -e init -Ttext 0x7c00 -o bootloader.bin bootloader.o
qemu-system-x86_64 bootloader.bin
没有任何附加内容(只是:“从硬盘启动......”)
我在 https://openclassrooms.com/forum/sujet/asm-boot-loader-91783 上没有找到解决方案 其他教程也是如此。
bootloader.s
.code16 # use 16 bits
.set BASE, 0x1000
.set KSIZE, 1
.global init
init:
mov $0x100, %ax
mov %ax, %ds
mov %ax, %es
# initialisation du segment de pile
mov $0x8000, %ax
mov %ax, %ss
mov $0xf000, %sp
mov $0x0e, %ah
in $0x64, %al
test $1, %al
jz init_next
in $0x60, %al
cmp $224, %al
je init_next
init_next:
mov BASE, %ax
mov %ax, %es
xor %bx, %bx
# charger le noyau
mov $0x02, %ah
mov KSIZE, %al
mov $0, %ch
mov $2, %cl
mov $0, %dh
mov $0, %dl
int $0x13
mov $'F', %al
int $0x10
# saut vers le kernel
jmp BASE
bootdrv: .int 0
.fill 510-(.-init), 1, 0
.word 0xaa55
.include "kernel.s"
内核.s
.code16
.global init
.org 0x1000
start:
mov $0x1000, %ax
mov %ax, %ds
mov %ax, %es
# initialisation du segment de pile
mov $0x8000, %ax
mov %ax, %ss
mov $0xf000, %sp
mov $0x0e, %ah
in $0x64, %al
test $1, %al
jz next
in $0x60, %al
cmp $224, %al
je next
data:
msg: .asciz "Hello world !"
msg2: .asciz "I hope you're well : "
test_int: .int 0
#msg3: .asciz "Just a test for the size of the bootloader"
print_str:
push %ax
.print_str__run:
lodsb
cmp $0, %al
je .print_str__done
int $0x10
jmp .print_str__run
.print_str__done:
pop %ax
ret
print_nl:
push %ax
.print_nl__run:
mov $10, %al
int $0x10
mov $13, %al
int $0x10
pop %ax
ret
input:
.input__run:
in $0x64, %al
and $1, %al
jz .input__run
in $0x60, %al # get input keyboard
mov %al, %bl
cmp $0x0, %bl
je .input__run
shr $4, %bl # move to right 4 bits
cmp $0x0, %bl
je .input__number
jmp .input__letter
.input__number:
add $47, %al
int $0x10
jmp .input__done
.input__letter:
cmp $0x10, %al
je .input__letter__a
cmp $0x11, %al
je .input__letter__z
cmp $0x12, %al
je .input__letter__e
cmp $0x13, %al
je .input__letter__r
cmp $0x14, %al
je .input__letter__t
cmp $0x15, %al
je .input__letter__y
cmp $0x16, %al
je .input__letter__u
cmp $0x17, %al
je .input__letter__i
cmp $0x18, %al
je .input__letter__o
cmp $0x19, %al
je .input__letter__p
cmp $0x1e, %al
je .input__letter__q
cmp $0x1f, %al
je .input__letter__s
cmp $0x20, %al
je .input__letter__d
cmp $0x21, %al
je .input__letter__f
cmp $0x22, %al
je .input__letter__g
cmp $0x23, %al
je .input__letter__h
cmp $0x24, %al
je .input__letter__j
cmp $0x25, %al
je .input__letter__k
cmp $0x26, %al
je .input__letter__l
cmp $0x27, %al
je .input__letter__m
cmp $0x2c, %al
je .input__letter__w
cmp $0x2d, %al
je .input__letter__x
cmp $0x2e, %al
je .input__letter__c
cmp $0x2f, %al
je .input__letter__v
cmp $0x30, %al
je .input__letter__b
cmp $0x31, %al
je .input__letter__n
cmp $0x39, %al
je .input__letter__space
jmp .input__run
.input__letter__a:
mov $'a', %al
int $0x10
jmp .input__done
.input__letter__z:
mov $'z', %al
int $0x10
jmp .input__done
.input__letter__e:
mov $'e', %al
int $0x10
jmp .input__done
.input__letter__r:
mov $'r', %al
int $0x10
jmp .input__done
.input__letter__t:
mov $'t', %al
int $0x10
jmp .input__done
.input__letter__y:
mov $'y', %al
int $0x10
jmp .input__done
.input__letter__u:
mov $'u', %al
int $0x10
jmp .input__done
.input__letter__i:
mov $'i', %al
int $0x10
jmp .input__done
.input__letter__o:
mov $'o', %al
int $0x10
jmp .input__done
.input__letter__p:
mov $'p', %al
int $0x10
jmp .input__done
.input__letter__q:
mov $'q', %al
int $0x10
jmp .input__done
.input__letter__s:
mov $'s', %al
int $0x10
jmp .input__done
.input__letter__d:
mov $'d', %al
int $0x10
jmp .input__done
.input__letter__f:
mov $'f', %al
int $0x10
jmp .input__done
.input__letter__g:
mov $'g', %al
int $0x10
jmp .input__done
.input__letter__h:
mov $'h', %al
int $0x10
jmp .input__done
.input__letter__j:
mov $'j', %al
int $0x10
jmp .input__done
.input__letter__k:
mov $'k', %al
int $0x10
jmp .input__done
.input__letter__l:
mov $'l', %al
int $0x10
jmp .input__done
.input__letter__m:
mov $'m', %al
int $0x10
jmp .input__done
.input__letter__w:
mov $'w', %al
int $0x10
jmp .input__done
.input__letter__x:
mov $'x', %al
int $0x10
jmp .input__done
.input__letter__c:
mov $'c', %al
int $0x10
jmp .input__done
.input__letter__v:
mov $'v', %al
int $0x10
jmp .input__done
.input__letter__b:
mov $'b', %al
int $0x10
jmp .input__done
.input__letter__n:
mov $'n', %al
int $0x10
jmp .input__done
.input__letter__space:
mov $' ', %al
int $0x10
jmp .input__done
.input__done:
ret
next:
.key_wait:
in $0x64, %al
and $1, %al
jz .key_wait
in $0x60, %al
cmp $0x10, %al # 'a' pressed
je .code
mov %al, %bl
cmp $0x0, %bl
je .key_wait
shr $4, %bl
cmp $0x0, %bl
je .number
jmp .normal
.number:
add $47, %al
int $0x10
jmp .key_wait
.normal:
int $0x10
jmp .key_wait
.code:
#mov $8, %al
#mov %al, test_int
call print_nl
mov $msg, %si
call print_str
call print_nl
mov $msg2, %si
call print_str
code__input:
call input
mov $0x0, %al
mov BASE, %ax mov %ax, %es xor %bx, %bx
看到kernel.s文件有一个
.org 0x1000
指令,我们知道.set BASE, 0x1000
指的是线性地址0x1000。为了让 BIOS 加载内核,我们应该将 %es:%bx
设置为 0x0000:0x1000。
xor %ax, %ax
mov %ax, %es
mov BASE, %bx
init: mov $0x100, %ax mov %ax, %ds mov %ax, %es
因为您的 bootloader.s 文件使用原点 7C00h,所以
%ds
和 %es
的正确设置为零:
init:
xor %ax, %ax
mov %ax, %ds
mov %ax, %es
.org 0x1000 start: mov $0x1000, %ax mov %ax, %ds mov %ax, %es
因为您的 kernel.s 文件使用
.org 0x1000
,所以 %ds
和 %es
的正确设置为零:
.org 0x1000
start:
xor %ax, %ax
mov %ax, %ds
mov %ax, %es
mov $0, %dl int $0x13 mov $'F', %al int $0x10
这
int $0x10
应该做什么?int $0x13
调用成功,则 %ah
仍将包含 0x02,但这将导致无意义的 SetCursorPosition 调用,如果 int $0x13
调用不成功,则 %ah
将保存一个状态字节,该状态字节将导致调用一些随机视频 BIOS 调用!
提示1:请务必检查BIOS向您报告的进位标志,以便您可以处理错误...
提示 2:最好省略
mov $0, %dl
指令并使用 BIOS 在将控制权传递给引导加载程序时放入 %dl
寄存器中的值。
cmp $224, %al je next data: msg: .asciz "Hello world !"
当
%al
不等于224时会发生什么?执行在某些数据中失败,绝对不是代码!
我建议一步一步地进行,并简化当前的代码(两个文件)以不使用那些与键盘相关的端口。
在需要键盘输入的地方,您应该使用 BIOS(就像您已经在使用其他任何东西一样):
mov ah, 00h ; BIOS.WaitKeyboardKeypress
int 16h ; -> AH is scancode, AL is ASCII code
当你快乐时,你会喜欢音乐,但当你悲伤时,你会理解歌词 จีจี https://google.co.th/