【问题标题】:C kernel- printing string not workingC内核打印字符串不起作用
【发布时间】:2015-05-30 22:56:51
【问题描述】:

我正在从头开始制作一个 C 内核,实际上我只是从网站上复制了这段代码,因为我的代码不起作用,所以我很困惑。

void kmain(void)
{
    const char *str = "my first kernel";
    char *vidptr = (char*)0xb8000;  //video mem begins here.
    unsigned int i = 0;
    unsigned int j = 0;

    /* this loops clears the screen
    * there are 25 lines each of 80 columns; each element takes 2 bytes */
    while(j < 80 * 25 * 2) {
        /* blank character */
        vidptr[j] = ' ';
        /* attribute-byte - light grey on black screen */
        vidptr[j+1] = 0x07;         
        j = j + 2;
    }

    j = 0;

    /* this loop writes the string to video memory */
    while(str[j] != '\0') {
        /* the character's ascii */
        vidptr[i] = str[j];
        /* attribute-byte: give character black bg and light grey fg */
        vidptr[i+1] = 0x07;
        ++j;
        i = i + 2;
    }
    return;
}

当我运行我的内核时,它会在屏幕上打印一个 S 而没有别的。我知道我的内核正在启动,因为如果我这样做了

vidptr[0] = 'h';
vidptr[2] = 'e';
vidptr[4] = 'l';
vidptr[6] = 'l';
vidptr[8] = 'o';

它按预期工作。发生了什么?

编辑:可能是我的代码加载了内核(可能没有设置一些寄存器),所以我只会研究 grub 和其他东西。

【问题讨论】:

  • 什么是 C 内核? C 只是一种编程语言
  • 这就是为什么你不会为了学习而复制代码。
  • @StefanFalk 对不起,我不清楚,我一直在研究我的内核,当我尝试制作打印功能时,我无法让它工作,所以我去了一个网站来尝试代码,看看它是否只是我的代码。
  • 它不可能使用您存储在数组 '0' != '\0' 中的值。
  • @iharob 是的,我也是这么想的。如果我只是做 vidptr[0] = str[0];它不起作用。

标签: c kernel


【解决方案1】:

尝试对变量使用 volatile 关键字

参考页面:http://wiki.osdev.org/Printing_To_Screen

// note this example will always write to the top
// line of the screen
void write_string( int colour, const char *string )
{
    volatile char *video = (volatile char*)0xB8000;
    while( *string != 0 )
    {
        *video++ = *string++;
        *video++ = colour;
    }
}

【讨论】:

    【解决方案2】:

    出于某种原因,如果我使用 char str[] = "blabla"; 而不是 char *str = "blabla"; 它可以工作。

    【讨论】:

    • 如果我这样做,我会收到链接器错误undefined reference to '__stack_chk_fail':/
    【解决方案3】:

    首先,你是在跳转Kernel之前还是在运行函数之前设置SP?如果没有,请适当设置。在您的启动函数中,您应该设置堆栈指针 DS、SS;您可以在程序开始时使用内联汇编。你也应该使用char var [] = "Something",而不是char * p = "Something",或者

    char var[10]; 
    var[1] = 'S'; 
    var[2] = 'o';
    

     char var[] = { 'S', 'o', 'm', 'e', ..., '\0' } ;
    

    我的引导加载程序建立 GDT 并切换到 32 位模式并跳转 (jmp 0x8:0x8000) 这里0x8 是我在 GDT 中的代码段地址,DS、SS 为 0x10;所以它跳转到内核。在我没有设置 SS、SP、DS 并且无法打印之前,我编写了这个小代码:

    [bits 32]
    
     MOV   AX, 0x10 ; 0x10 points at the new data selector
     MOV   DS, eax
     MOV   ES, AX
     MOV   FS, AX
     MOV   GS, AX
     MOV   SS, AX
     MOV  eax, 0x200000
     MOV  esp, eax 
    

    并使用nasm 编译它,并使用 HEX 编辑器程序手动添加到内核程序的开头。

    【讨论】:

    • 请在以后正确格式化您的代码部分。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-04
    相关资源
    最近更新 更多