如何将文本添加到用汇编编写的 OS

How to add text to OS written in assembly

所以我开始学习汇编,并且正在用 FASM 编写一个简单的 OS。我有一个带有灰色顶栏和光标的蓝屏,但无法让文本出现在一行上。在第一行我希望它说 "FILE SYSTEM" 然后在其他行我想要其他东西。我会把代码放在这里:

mov ax, 9ch
mov ss, ax
mov sp, 4096d
mov ax, 7c0h
mov ds, ax
;----------------


;this sets blue to background
mov ah, 09h
mov cx, 1000h
mov al, 20h
mov bl, 17h
int 10h
;end of blue

;start of gray top
mov ah, 09h
mov cx, 80d
mov al, 20h
mov bl, 87h
int 10h
;end of gray
;top bar






;end of top bar
;define mouse
mov ah, 01h
mov cx, 07h
int 10h

mov bl, 5h
mov cl, 5h


_mouser:
mov ah, 02h
mov dl, bl
mov dh, cl
int 10h

mov ah, 00h
int 16h

cmp al, 77h
je _up
cmp al, 73h
je _down
cmp al, 61h
je _left
cmp al, 64h
je _right
cmp al, 20h
je _click
jmp _mouser



_click:
mov ah, 0eh
mov al, 0b2h
int 10h
jmp _mouser

_up:
cmp cl, 0h
je _mouser
sub cl, 1h
jmp _mouser

_down:
cmp cl, 24d
je _mouser
add cl, 1h
jmp _mouser

_left:
cmp bl, 0h
je _mouser
sub bl, 1h
jmp _mouser

_right:
cmp bl, 79d
je _mouser
add bl, 1h
jmp _mouser



;----------------
times 510-($-$$) db 0
dw 0xAA55

我试过了

mov ah, eoh
mov al, 'F'
int 10h

问题是只能生成单个字符而不是字符串。

PC 的 ROM BIOS 提供了一组视频服务,通过中断 10h 调用,包括一些将字符打印到字符串的服务。可在 here.

中找到有关它们的综合文档

看来你已经发现了服务0Eh,它在当前字符位置向屏幕写入一个字符,并向前移动字符位置。这将屏幕视为电传打字机 (TTY),并且非常容易在屏幕上获得输出。

(至少,它 看起来 就像您在尝试调用服务 0Eh。您的代码不正确。您有 mov ah, eoh,这是不正确的. o 不是十六进制值,即使这是 0 的拼写错误,您也将半字节颠倒了。它应该是 mov ah, 0Eh。)

如果你想打印一个字符串(多个字符),你基本上有两个选择:

  1. 您可以迭代调用类似 0Eh 的服务,每次将一个字符写入字符串。一个示例实现是:

        mov  ah, 0Eh             ; service 0Eh: print char as TTY
    .PrintNextChar:
        mov  al, BYTE PTR [si]   ; get next character in string, pointed to by SI
        inc  si                  ; increment pointer
        test al, al              ; is character == 0 (end-of-string)?
        je   .Done
        int  10h
        jmp  .PrintNextChar
    .Done
    

    这会打印 SI 指向的字符串中的字符,直到它到达 0(NUL 字符),这表示字符串的结尾(标准的 C 样式 NUL 终止字符串)。

    但是,这种一次打印一个字符的方法相对较慢。相反,人们通常更喜欢……

  2. 使用服务 1300h 或 1301h 一次打印整个字符串。区别在于服务 1301h 在打印字符串后使光标前进,而服务 1300h 不更改光标。否则,它们是相同的。

    这些服务的参数记录在上面的 link 中;为方便起见转载于此:

    • AX == 1300h/1301h
    • BL == 视频属性(文本模式下,指定前景色和背景色)
    • BH ==视频页面(通常为0)
    • CX == 字符串长度
    • DL/DH == column/row 字符串的起始位置
    • ES:BP == 字符串开头地址

    显然这需要你事先知道字符串的长度,并将其作为参数传入CX寄存器中。该字符串由 ES:BP.

    指向

    在您的例子中,要打印 "FILE SYSTEM",您需要在包含该字符串的 DATA 段中声明一个字符数组,然后执行如下操作:

    MyString DB "FILE SYSTEM"
    
    mov  ax, ds
    mov  es, ax          ; set ES == DS
    mov  bp, MyString
    mov  cx, 11          ; length of string (number of chars)
    mov  bx, 07h         ; foreground & background color (white on black)
    xor  dx, dx          ; starting position (top-left)
    mov  ax, 1301h       ; service 1301h: print string and update cursor
    int  10h