assembly - 为什么这个简单的 Forth 不写入 VGA 文本缓冲区?

标签 assembly x86-64 nasm bootloader multiboot

我正在尝试为 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_entry 部分中放置写入“A”的指令效果很好。

最佳答案

正如 Jester 所指出的,我正在编写 64 位程序集,但引导加载程序仅提供 32 位保护模式。

关于assembly - 为什么这个简单的 Forth 不写入 VGA 文本缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76440626/

相关文章:

assembly - 零/符号扩展是空操作,那么为什么要对每种尺寸类型进行说明呢?

x86 - "unscrambled"在这种情况下是什么意思?

c - 如何定义 80 位大小的变量

linux - 如何更改 gcc 生成的 asm 代码的入口点?

linux - 如何在 x86 汇编中调用 fgets?

c++ - 如何将 WebAssembly 编译成常规汇编/ native 代码(或 Cpp 等)?

c - 是否可以添加 getchar();相当于 .o 文件?

unix - 64 位快速调用

linux - 文件读取缓冲区在 nasm 中为空

linux - 在 nasm 程序集中的 .data 段之外声明字符串