assembly - 如何更改字符串的前景色(32 位汇编内核)?

标签 assembly x86 kernel osdev vga

我目前正在编写自己的操作系统(只是为了好玩,我今年 16 岁)并且我创建的 outprint 函数有问题。我想更改文本颜色(不是背景颜色),但它不起作用。

我创建了我自己的 printf 函数 SystemOutPrint/ln(以 Java 命名,因为那是我的“主要”语言,对于那些受伤的人)并且发现我可以通过写入 AH 寄存器来改变背景颜色。在此功能之前,我在内核中什么也没做,引导加载程序仅设置 GDT、LDT 和从 16 位到 32 位的模式。所以视频内存在 mov ebx, 0xb8000 之前没有被触及。

相关代码:

kmain:
mov ebx, 0xb8000    ;Video Memory
mov esi, kernelVersion
mov ah, 0x0
;setting ah to 0x0 is not neccessary, because its the default but if you
;would put in A for example it would be light green, etc.
call SystemOutPrintln

SystemOutPrintln:
mov ecx, ebx

.printChar:
lodsb
test al,al
jz .newLine
or eax,0x0F00
mov word [ebx], ax
add ebx, 2
jmp .printChar

.newLine:
mov edx, ebx
sub edx, ecx
mov ecx, 0x000A0
sub ecx, edx
add ebx, ecx
ret

kernelVersion: db "Kernel Version: 0.0.1", 0

我尝试了什么: 更改 eax 中的每个字节以查找前景色的属性字节。通过这样的尝试和错误,我发现改变 ah 对背景颜色有效,但是 al 用于测试 al,al 来查找字符串的结尾,而 eax 中不是 ax 的部分被简单地忽略了功能。我没有尝试更改其他寄存器中的内容,因为它们被用于其他用途或根本没有用途,所以它对我来说没有意义。一个网站(我没有找到链接)说属性字节是这样定义的: BG 颜色的十六进制值(比如 F 代表白色)* 16 = F0 + FG 颜色的十六进制值(让 A 代表浅绿色)什么应该是FA。如果我执行“mov ah, 0xFA”,我会将背景更改为白色,但前景仍然是白色(默认)。

为此提供一个最小的可复制示例将不再是最小的,因为我还必须为您提供引导加载程序和 GDT。但是,如果有人能告诉我哪个字节是前景颜色属性字节,这就足够了,这样我就可以专注于尝试使该字节正常工作,而不必在尝试和错误中重写整个视频内存。

最佳答案

首先;让我们稍微优化一下您的代码。具体来说,对于这个循环:

.printChar:
    lodsb
    or al,al
    jz .newLine
    or eax,0x0F00
    mov word [ebx], ax
    add ebx, 2
    jmp .printChar

..在第一次迭代之后,ah 中的值不会改变;这样指令就可以脱离循环以提高性能。 or eax,0x0F000 与较短的 or ah,0x0F 具有相同的效果。通过这两项更改,它最终变成了这样:

    or ah,0x0F
.printChar:
    lodsb
    or al,al
    jz .newLine
    mov word [ebx], ax
    add ebx, 2
    jmp .printChar

现在添加一些评论,如下所示:

    or ah,0x0F          ;Force the foreground colour for all characters to be white
.printChar:
    lodsb               ;al = next character
    or al,al            ;Is the next character zero?
    jz .newLine         ; yes, don't print it and move to the next line instead
    mov word [ebx], ax  ;Store next character (from string) and attribute (from outside the loop)
    add ebx, 2          ;bx = address to store next character and attribute
    jmp .printChar

请注意注释(例如“强制所有字符的前景色为白色”)很有用,因为:

  • 他们减少了理解代码应该做什么的时间

  • 它们可以很容易地发现指令没有执行注释所说的应该执行的错误

关于assembly - 如何更改字符串的前景色(32 位汇编内核)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57412148/

相关文章:

c - While 循环遍历数组,MIPS 汇编

c++ - Clang 对于 7 次比较生成的代码比 8 次比较生成的代码更差

c++ - 线性代数的CPU指令集?

c++ - 从任何内存地址读取 UInt32 的最有效方法?

linux - 为什么根据 LDD3 device->kobj->parent 等于 &device->parent->kobj?

c - fseek 的性能开销是多少?

loops - AVR 组装 BRNE 延迟循环如何工作?

assembly - 我的操作系统无法在 VMWare 中启动

linux - 参数类型 : "const char __user *const __user *argv" 的含义是什么

c - C中的汇编代码是什么?