在保护模式下将字符打印到屏幕 ASM
Printing characters to screen ASM in protected mode
我正在尝试进入保护模式然后打印出来"Hi"
但它只是从我的 bios 中断调用(在进入 pmode 之前发生)打印 "Loading OS" 而没有别的。
我的Bootloader.asm
%DEFINE KERNEL_LOAD_OFFSET 0x1000
org 0x7c00
bits 16
xor ax, ax
mov ds, ax
start: jmp main
Print:
.print:
lodsb
or al, al
je .done
mov ah, 0x0E
int 0x10
.repeat:
jmp .print
.done:
ret
ResetFloppy:
mov ah, 0x0
int 0x13
jc ErrorFloppy
.done:
ret
ReadFloppy:
mov ah, 0x02
int 0x13
jc ErrorFloppy
.done:
ret
ErrorFloppy:
mov si, msgErrorFloppy
call Print
jmp hang
main:
.print:
mov si, msg
call Print
.loadFile:
mov al, 0xF
mov ch, 0x0
mov cl, 0x02
mov dh, 0x0
mov dl, 0x0
mov bx, KERNEL_LOAD_OFFSET
call ResetFloppy
call ReadFloppy
.loadGDT:
lgdt [gdtr]
.pM_start:
cli
pusha
mov eax, cr0
or al, 1
mov cr0, eax
popa
jmp 0x08:ljmp_pM
bits 32
ljmp_pM:
mov ax, 0x10
mov ds, ax
mov ss, ax
mov fs, ax
mov es, ax
mov gs, ax
jmp KERNEL_LOAD_OFFSET
hang:
jmp $
gdt:
NULL_DESC:
dd 0 ; null descriptor
dd 0
CODE_DESC:
dw 0xFFFF ; limit low
dw 0 ; base low
db 0 ; base middle
db 10011010b ; access
db 11001111b ; granularity
db 0 ; base high
DATA_DESC:
dw 0xFFFF ; data descriptor
dw 0 ; limit low
db 0 ; base low
db 10010010b ; access
db 11001111b ; granularity
db 0 ; base high
gdtr:
Limit dw 24 ; length of GDT
Base dd NULL_DESC ; base of GDT
msg db "Loading OS", 13, 10, 0
msgErrorFloppy db "There was an error with the floppy", 13, 10, 0
FILL:
times 510-($-$$) db 0
BOOTSECTOR:
dw 0xAA55
Kernel.asm
bits 32
mov dword [0xB8000], 0x07690748
jmp $
和Compile.bat
nasm -f bin Dev/BootLoader.asm -o Bin/BootLoader.bin
nasm -f bin Dev/Kernel.asm -o Bin/Kernel.bin
dd if=Bin/BootLoader.bin of=Image/Image.img seek=0
dd if=Bin/Kernel.bin of=Image/Image.img seek=1 conv=notrunc
pause
我用的是bochs。我得到的只是:http://prntscr.com/d24wmm
在 32 位保护模式下,您无法使用 BIOS,因为它是用 16 位实模式代码编写的。所以,你必须像这样访问显存:
mov ebx,0xb8000 ; The video address
mov al,'!' ; The character to be print
mov ah,0x0F ; The color: white(F) on black(0)
mov [ebx],ax ; Put the character into the video memory
然后您可能会在屏幕的开头看到一个 !
。如果只想在光标位置打印,可以这样获取光标偏移量:
mov dx,0x3D4 ; Tell the control I/O port to get the lower byte of
mov al,0x0F ; the cursor offset
out dx,al
mov dx,0x3D5 ; Switch to data I/O port
in al,dx ; Get the cursor offset's lower byte
mov dx,0x3D5 ; Tell the control I/O port to get the higher byte of
mov al,0x0E ; the cursor offset
out dx,al
mov dx,0x3D5 ; Switch to data I/O port
in al,dx ; Get the higher byte
imul ax,2 ; Because a character in video memory costs 2 bytes
; (i.e character and attribute), we need to twice the cursor offset
In 32-bit protected mode, to increase your code's efficiency, you could use some high-level language like C
to create the functions. This really increased the readability of the code.
我正在尝试进入保护模式然后打印出来"Hi"
但它只是从我的 bios 中断调用(在进入 pmode 之前发生)打印 "Loading OS" 而没有别的。
我的Bootloader.asm
%DEFINE KERNEL_LOAD_OFFSET 0x1000
org 0x7c00
bits 16
xor ax, ax
mov ds, ax
start: jmp main
Print:
.print:
lodsb
or al, al
je .done
mov ah, 0x0E
int 0x10
.repeat:
jmp .print
.done:
ret
ResetFloppy:
mov ah, 0x0
int 0x13
jc ErrorFloppy
.done:
ret
ReadFloppy:
mov ah, 0x02
int 0x13
jc ErrorFloppy
.done:
ret
ErrorFloppy:
mov si, msgErrorFloppy
call Print
jmp hang
main:
.print:
mov si, msg
call Print
.loadFile:
mov al, 0xF
mov ch, 0x0
mov cl, 0x02
mov dh, 0x0
mov dl, 0x0
mov bx, KERNEL_LOAD_OFFSET
call ResetFloppy
call ReadFloppy
.loadGDT:
lgdt [gdtr]
.pM_start:
cli
pusha
mov eax, cr0
or al, 1
mov cr0, eax
popa
jmp 0x08:ljmp_pM
bits 32
ljmp_pM:
mov ax, 0x10
mov ds, ax
mov ss, ax
mov fs, ax
mov es, ax
mov gs, ax
jmp KERNEL_LOAD_OFFSET
hang:
jmp $
gdt:
NULL_DESC:
dd 0 ; null descriptor
dd 0
CODE_DESC:
dw 0xFFFF ; limit low
dw 0 ; base low
db 0 ; base middle
db 10011010b ; access
db 11001111b ; granularity
db 0 ; base high
DATA_DESC:
dw 0xFFFF ; data descriptor
dw 0 ; limit low
db 0 ; base low
db 10010010b ; access
db 11001111b ; granularity
db 0 ; base high
gdtr:
Limit dw 24 ; length of GDT
Base dd NULL_DESC ; base of GDT
msg db "Loading OS", 13, 10, 0
msgErrorFloppy db "There was an error with the floppy", 13, 10, 0
FILL:
times 510-($-$$) db 0
BOOTSECTOR:
dw 0xAA55
Kernel.asm
bits 32
mov dword [0xB8000], 0x07690748
jmp $
和Compile.bat
nasm -f bin Dev/BootLoader.asm -o Bin/BootLoader.bin
nasm -f bin Dev/Kernel.asm -o Bin/Kernel.bin
dd if=Bin/BootLoader.bin of=Image/Image.img seek=0
dd if=Bin/Kernel.bin of=Image/Image.img seek=1 conv=notrunc
pause
我用的是bochs。我得到的只是:http://prntscr.com/d24wmm
在 32 位保护模式下,您无法使用 BIOS,因为它是用 16 位实模式代码编写的。所以,你必须像这样访问显存:
mov ebx,0xb8000 ; The video address
mov al,'!' ; The character to be print
mov ah,0x0F ; The color: white(F) on black(0)
mov [ebx],ax ; Put the character into the video memory
然后您可能会在屏幕的开头看到一个 !
。如果只想在光标位置打印,可以这样获取光标偏移量:
mov dx,0x3D4 ; Tell the control I/O port to get the lower byte of
mov al,0x0F ; the cursor offset
out dx,al
mov dx,0x3D5 ; Switch to data I/O port
in al,dx ; Get the cursor offset's lower byte
mov dx,0x3D5 ; Tell the control I/O port to get the higher byte of
mov al,0x0E ; the cursor offset
out dx,al
mov dx,0x3D5 ; Switch to data I/O port
in al,dx ; Get the higher byte
imul ax,2 ; Because a character in video memory costs 2 bytes
; (i.e character and attribute), we need to twice the cursor offset
In 32-bit protected mode, to increase your code's efficiency, you could use some high-level language like
C
to create the functions. This really increased the readability of the code.