Gcc 内核主函数中这个神秘的字符是什么?我怎样才能删除它?
我正试图按照链接创建自己的内核 作者提到“后面跟着一些神秘的人物。” 为什么会出现这个角色?我怎样才能删除它 我正在使用kernel.c文件,只是将kernel main更改为打印ASCII字符Gcc 内核主函数中这个神秘的字符是什么?我怎样才能删除它?,gcc,terminal,x86,kernel,osdev,Gcc,Terminal,X86,Kernel,Osdev,我正试图按照链接创建自己的内核 作者提到“后面跟着一些神秘的人物。” 为什么会出现这个角色?我怎样才能删除它 我正在使用kernel.c文件,只是将kernel main更改为打印ASCII字符 void kernel_main(void) { terminal_initialize(); terminal_writestring(" ____ ___ ____"); termina
void kernel_main(void)
{
terminal_initialize();
terminal_writestring(" ____ ___ ____");
terminal_putchar('\n');
terminal_writestring("| _ \\ _ _ _ __ ___ __ _ / _ \\/ ___|");
terminal_putchar('\n');
terminal_writestring("| |_) | | | | '_ ` _ \\ / _` | | | \\___ \\");
terminal_putchar('\n');
terminal_writestring("| __/| |_| | | | | | | (_| | |_| |___) |");
terminal_putchar('\n');
terminal_writestring("|_| \\__,_|_| |_| |_|\\__,_|\\___/|____/");
terminal_putchar('\n');
}
这是我的结果
@Ken Y-N是正确的,因为您应该编写
\r\N
而不是\N
(即,CRLF而不是LF)
然而,更好的解决方案(我认为)是:
a) 检查字符是否为终端putchar
中的\n
,是否只是将终端列
设置为0,并将终端行
增加一个:
void terminal_putchar(char c)
{
/* check that the previous character wasn't a '\r', if it was print CRLF as normal */
if (c == '\n' && terminal_buffer[terminal_column * VGA_WIDTH + terminal_row] != '\r') {
/* move cursor to start of next line (without printing a CRLF) */
terminal_column = 0;
terminal_row += 1;
return;
}
terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
if (++terminal_column == VGA_WIDTH) {
terminal_column = 0;
if (++terminal_row == VGA_HEIGHT)
terminal_row = 0;
}
}
或者更好的方法是b)检查字符是否在终端\u putchar
中\n
,如果是,则打印CRLF:
void terminal_putchar(char c)
{
/* turn LF -> CRLF if missing CR */
if (c == '\n' && terminal_buffer[terminal_column * VGA_WIDTH + terminal_row] != '\r') {
terminal_putentryat('\r', terminal_color, terminal_column, terminal_row);
}
terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
if (++terminal_column == VGA_WIDTH) {
terminal_column = 0;
if (++terminal_row == VGA_HEIGHT)
terminal_row = 0;
}
}
希望有帮助
编辑:对于一些额外的优化,您可以检测一个\r
并设置一些布尔可用值(例如一个1或0的int),然后用该布尔可用值的名称替换终端缓冲区[terminal\u column…
。这允许保证4字节对齐的访问,这总是更快(有关更多信息,请参阅)。示例代码:
uint8_t was_cr = 0;
void terminal_putchar(char c)
{
/* turn LF -> CRLF if missing CR */
if (c == '\n' && !was_cr) {
terminal_putentryat('\r', terminal_color, terminal_column, terminal_row);
}
/* at this point was_cr has already been read */
/* considering that was_cr is read every time this function is called, */
/* it is likely that the CPU will cache it's value, so read times will be short */
/* even if it isn't cached, memory reads are always faster than memory writes */
if (c == '\r' && !was_cr) was_cr = 1;
else if (was_cr) was_cr = 0;
terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
if (++terminal_column == VGA_WIDTH) {
terminal_column = 0;
if (++terminal_row == VGA_HEIGHT)
terminal_row = 0;
}
}
@Ken Y-N是正确的,因为您应该编写
\r\N
而不是\N
(即CRLF而不是LF)
然而,更好的解决方案(我认为)是:
a) 检查字符是否为终端putchar
中的\n
,是否只是将终端列
设置为0,并将终端行
增加一个:
void terminal_putchar(char c)
{
/* check that the previous character wasn't a '\r', if it was print CRLF as normal */
if (c == '\n' && terminal_buffer[terminal_column * VGA_WIDTH + terminal_row] != '\r') {
/* move cursor to start of next line (without printing a CRLF) */
terminal_column = 0;
terminal_row += 1;
return;
}
terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
if (++terminal_column == VGA_WIDTH) {
terminal_column = 0;
if (++terminal_row == VGA_HEIGHT)
terminal_row = 0;
}
}
或者更好的方法是b)检查字符是否在终端\u putchar
中\n
,如果是,则打印CRLF:
void terminal_putchar(char c)
{
/* turn LF -> CRLF if missing CR */
if (c == '\n' && terminal_buffer[terminal_column * VGA_WIDTH + terminal_row] != '\r') {
terminal_putentryat('\r', terminal_color, terminal_column, terminal_row);
}
terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
if (++terminal_column == VGA_WIDTH) {
terminal_column = 0;
if (++terminal_row == VGA_HEIGHT)
terminal_row = 0;
}
}
希望有帮助
编辑:对于一些额外的优化,您可以检测一个\r
并设置一些布尔可用值(例如一个1或0的int),然后用该布尔可用值的名称替换终端缓冲区[terminal\u column…
。这允许保证4字节对齐的访问,这总是更快(有关更多信息,请参阅)。示例代码:
uint8_t was_cr = 0;
void terminal_putchar(char c)
{
/* turn LF -> CRLF if missing CR */
if (c == '\n' && !was_cr) {
terminal_putentryat('\r', terminal_color, terminal_column, terminal_row);
}
/* at this point was_cr has already been read */
/* considering that was_cr is read every time this function is called, */
/* it is likely that the CPU will cache it's value, so read times will be short */
/* even if it isn't cached, memory reads are always faster than memory writes */
if (c == '\r' && !was_cr) was_cr = 1;
else if (was_cr) was_cr = 0;
terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
if (++terminal_column == VGA_WIDTH) {
terminal_column = 0;
if (++terminal_row == VGA_HEIGHT)
terminal_row = 0;
}
}
请发布
终端\u writestring()
的代码,但我认为问题在于它将'\r\n'
写入,而不是仅将'\n'
写入行尾。问题是奇数符号是与\n
相关联的字符(换行符)。字符集为。从输出中可以清楚地看出,您的代码将\n
视为\r\n
(换行和回车)当它转到下一行的第一列时。如果这是您想要的行为,那么您所要做的就是更新光标位置,但扔掉\n
而不是打印它。您的代码当前正在打印\n
并将光标更新到下一行的开头。您不需要的其他字符nt直接打印到屏幕上-制表符(\t)、回车符(\r)、换行符(\n)、退格符(\b)。所有这些都必须经过特殊处理。您能给我们展示terminal\u putchar函数的代码吗?请发布terminal\u writestring()的代码
,但我认为问题在于它写的是'\r\n'
,而不是仅仅在行尾写'\n'
。问题在于奇数符号是与\n
(换行符)相关联的字符。字符集是。从输出中可以清楚地看出,代码将\n
视为\r\n
(换行和回车)当它转到下一行的第一列时。如果这是您想要的行为,那么您所要做的就是更新光标位置,但扔掉\n
而不是打印它。您的代码当前正在打印\n
并将光标更新到下一行的开头。您不需要的其他字符nt直接打印到屏幕-制表符(\t)、回车符(\r)、换行符(\n)、退格符(\b)。所有这些都必须经过特殊处理。你能给我们看一下terminal_putchar函数的代码吗?我认为问题的真正关键是@MichaelPetch在评论中指出的:当你检测到新行时,你不必将其复制到屏幕上,只需移动光标。你在回答的文本中没有提到这一点,只有一个小的共点如果您不打算在字符串中包含\n
,您可以为终端换行设置一个单独的函数,不必检查任何内容,只需重置列和递增的行。如果您确实想以writestring/putchar处理\n
,那么可以在调用程序中利用它。@PeterCordes Hi,感谢我的想法,我正在逐字打印“\n”,如何省略转义序列(\n、\r、\t等)并像往常一样处理代码?是否使用字符串功能等?-复制strlen-2(\n)要设置缓冲区,然后打印缓冲区?@varun_koganti:显然,最简单的方法是一次循环字符串1个字节,并检查特殊情况,否则只能复制字符并更新列。例如,对每个字符分别使用writestring调用putchar。这将处理出现\n
或\n
,你可以e终端换行符的单独函数