我正在尝试为x86-64编写一个裸机Forth,使用Multiboot启动,但不使用ELF。为了检查我的进度,我试图让它写一个'A'字符的VGA文本输出,使用的话,我已经定义。下面是NASM大会:
[BITS 64]
LOADBASE equ 0x00100000
org LOADBASE
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ 0x00010000
CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
PS_SIZE equ 0x4000
CS_SIZE equ 0x4000
_start: ; in case we're using a custom bootloader
jmp boot_entry
align 4
multiboot_header:
dd MULTIBOOT_HEADER_MAGIC
dd MULTIBOOT_HEADER_FLAGS
dd CHECKSUM
dd multiboot_header ; location of this header
dd LOADBASE ; where to load the kernel
dd end ; where to finish loading
dd 00 ; bss end adress : not necessary
dd boot_entry ; entry point
%macro next 0
mov rax, qword[rsi]
add rsi, 8
jmp [rax]
%endmacro
boot_entry:
mov rsp, end + PS_SIZE
mov rbp, end + PS_SIZE + CS_SIZE
push rbx ; multiboot info
push rax
mov rsi, cold_start
next
%macro pushc 1
sub rbp, 8
mov qword[rbp], %1
%endmacro
%macro popc 1
mov %1, qword[rbp]
add rbp, 8
%endmacro
%define link 0
%macro DP 2 ; define a primitive (name, label)
%strlen namelen %1
align 4
global name_%2
name_%2:
dd link
%define link name_%2
db %1
align 4
global %2
%2:
dq code_%2
align 4
global code_%2
code_%2:
%endmacro
%macro DC 2 ; define a colon word (name, label)
%strlen namelen %1
align 4
global name_%2
name_%2:
dd link
%define link name_%2
db %1
align 4
global %2
%2:
dq docol
%endmacro
docol:
pushc rsi
add rax, 8
mov rsi, rax
next
cold_start:
dq QUIT
DC "QUIT", QUIT
dq LIT, 0x41, SHOW, QUIT
DC "SHOW", SHOW
dq LIT, 0xB8000, BWRITE, LIT, 0x07, LIT, 0xB8001, BWRITE, EXIT
DP "EXIT", EXIT
popc rsi
next
DP "B@", BREAD
pop rax
mov bl, byte[rax]
push rbx
next
DP "B!", BWRITE
pop rax
pop rbx
mov byte[rax], bl
next
DP "LIT", LIT
push qword[rsi]
add rsi, 8
next
end:
当然,此时宏的链表部分是不必要的,可以忽略。
我的问题是,这并没有写任何东西的VGA文本输出。到目前为止,我已经排除了 Boot 问题,因为在boot_entry
部分中放置写入'A'的指令可以正常工作。
1条答案
按热度按时间czfnxgou1#
正如Jester所指出的,我正在编写64位汇编,但引导加载程序只提供32位保护模式。