Assembly 在保护模式下向屏幕ASM打印字符
我正在尝试进入保护模式,然后打印“嗨” 但它只是从我的bios中断调用(发生在进入pmode之前)打印“加载操作系统”,没有其他内容 我的引导加载程序.asmAssembly 在保护模式下向屏幕ASM打印字符,assembly,x86,nasm,vga,bochs,Assembly,X86,Nasm,Vga,Bochs,我正在尝试进入保护模式,然后打印“嗨” 但它只是从我的bios中断调用(发生在进入pmode之前)打印“加载操作系统”,没有其他内容 我的引导加载程序.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
%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
bits 32
mov dword [0xB8000], 0x07690748
jmp $
Kernel.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
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。我所得到的是:在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
然后您可能会看到一个代码>在屏幕的开头。如果只想在光标位置打印,可以按如下方式获得光标偏移:
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
在32位保护模式下,为了提高代码的效率,可以使用一些高级语言,如C
来创建函数。这确实提高了代码的可读性
嗯,Hi
就在左上角?哦,我的天啊,我真是太傻了:D谢谢:D把这篇文章作为答案发出去你的第一个代码块不会存储到内存中。我认为您遗漏了一个mov[ebx],ax
,因为您假设分页被禁用或直接映射。顺便说一句,您可以编写mov-word[0xb8000],(0x0F也是,mul-ax,2
不是x86指令。imul-ax,2
是有效的,但用它乘以一个愚蠢的幂。使用shl-ax,1
。在写入al
和移位之前,不要忘记将eax
归零。使用shl-ax,1
。这里没有理由使用imul
的幂2.@PeterCordes我相信shift可能有一些错误。作为程序员,你应该知道第一位决定了符号,所以不使用shl更安全。