如何更改字符串的前景色(32 位汇编内核)?
How to change the foreground color of a string (32 Bit Assembly kernel)?
我目前正在编写自己的操作系统(只是为了好玩,我今年 16 岁)并且我创建的 outprint 函数有问题。我想更改文本颜色(不是背景颜色),但行不通。
我创建了自己的 printf
函数 SystemOutPrint/ln
(以 Java 命名,因为那是我的 "main" 语言,供那些受伤的人使用)并发现我可以通过写入 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 的部分被简单地忽略了功能。我没有尝试更改其他寄存器中的内容,因为它们被用于其他用途或根本没有用途,所以它对我来说没有意义。一个网站(我没有找到 link 它)说属性字节是这样定义的: 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
请注意注释(例如 "Force the foreground colour for all characters to be white")很有用,因为:
他们减少了理解代码应该做什么的时间
它们可以很容易地看到指令没有按照评论所说的去做的错误
我无法更改 FG 颜色的原因是 eax, 0x0f00
。
f
是应该定义前景色的半字节,但由于 or
,我之前放在那里的所有内容都被覆盖了。感谢 Peter Cordes 询问我为什么是 "using or eax, 0x0f00
inside the loop instead of just setting AH once outside the loop." 因此我试图将 or
排除在外并且它按照预期的方式工作,只是不再忽略我之前设置的 FG。
我目前正在编写自己的操作系统(只是为了好玩,我今年 16 岁)并且我创建的 outprint 函数有问题。我想更改文本颜色(不是背景颜色),但行不通。
我创建了自己的 printf
函数 SystemOutPrint/ln
(以 Java 命名,因为那是我的 "main" 语言,供那些受伤的人使用)并发现我可以通过写入 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 的部分被简单地忽略了功能。我没有尝试更改其他寄存器中的内容,因为它们被用于其他用途或根本没有用途,所以它对我来说没有意义。一个网站(我没有找到 link 它)说属性字节是这样定义的: 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
请注意注释(例如 "Force the foreground colour for all characters to be white")很有用,因为:
他们减少了理解代码应该做什么的时间
它们可以很容易地看到指令没有按照评论所说的去做的错误
我无法更改 FG 颜色的原因是 eax, 0x0f00
。
f
是应该定义前景色的半字节,但由于 or
,我之前放在那里的所有内容都被覆盖了。感谢 Peter Cordes 询问我为什么是 "using or eax, 0x0f00
inside the loop instead of just setting AH once outside the loop." 因此我试图将 or
排除在外并且它按照预期的方式工作,只是不再忽略我之前设置的 FG。