0

我正在尝试实现一个非常简单的函数来在我的内核中打印字符串。

这个麻烦对我来说似乎很奇怪,我在想我可能错过了一些重要的事情,但我不知道是什么。

所以,我有一个不起作用的代码:

void print (char c) {
    static unsigned i =0;
    if (c == '\n')
        i += 80 - i % 80;
    else {
        *(reinterpret_cast<uint16_t*>(0xb8000) + i) 
             = static_cast<uint16_t>(c) | 0x0f << 8;
        ++i;
    }
}
void print (const char* txt) {
    for (int i=0; txt[i]!=0; ++i)
        print(txt[i]);
}

请查看此摘录中的第 3 行: if (c=='\n') 如果我将其更改为无辜者会怎样: if (false) 那么它神奇地完美地工作......它不适用于 if(c =='T') 或其他任何东西,反正我的测试代码中还没有 '\n' :

print("test");

我想知道是否出于某种模糊的原因,

i += 80 - i % 80;

部分正在制造麻烦,但如果我用分号更改它并没有更好的效果......

但这还不是全部。我正在使用这些标志进行编译:

 clang++ -target i386 -std=c++11 -O2 -fno-builtin -nostdlib -ffreestanding -fno-exceptions -fno-rtti

如果我删除优化标志“-O2”,那么它在任何情况下都不会起作用。

我不明白我想念什么...请,你能帮帮我吗?我快疯了:P

=============编辑==============

经过调查,默认 qemu 设置似乎不支持 mtrrs(我使用特定的 cpu 设置检查了这一点)。在这里检查代码:(值得注意的是,osdev 说检查第 5 位,而 intel 说第 12 位,后者似乎在 qemu 下工作)

bool msr () {
    uint32_t eax, edx;
    cpu::cpuid(0x01, eax, edx);
    return edx & (1<<12);
}

这是我当前的代码库。

void print (char c) {
    static unsigned i =0;
    if (c == '\n')
        i += 80 - i % 80;
    else {
        volatile const auto b = reinterpret_cast<uint16_t*>(0xb8000);
        b[i++] = static_cast<uint16_t>(c) | 0x0f << 8;
    }
}
void print (const char* txt) {
    for (int i=0; txt[i]!=0; ++i)
        print(txt[i]);
}

//==============================================================================
// kmain
//==============================================================================
[[noreturn]] extern "C" void kmain () {

    __asm__ __volatile__(
            "mov    %%cr0, %%eax            \n"
            "or     $(1<<30), %%eax         \n"
            "mov    %%eax, %%cr0            \n"
            "wbinvd                         \n"
            :
            :
            : "eax");
    print("text text text");

    for (;;);
}

这里的 asm 部分是设置 cr0 中的第 30 位,英特尔声称这是禁用缓存。这仍然会打印第一个字母,而打印较短的字符串则很好......

我不知道现在要搜索什么。你有什么主意吗 ?十分感谢

=============编辑==============

哇,刚刚发现了一个不错的bug...

解决方案在链接描述文件中:

.rodata BLOCK(4K) : ALIGN(4K) {
    *(.rodata)
}

变成:

.rodata BLOCK(4K) : ALIGN(4K) {
    *(.rodata*)
}

只是因为 clang 生成的不是.rodata部分,而是.rodata.str1.1部分。这导致缺少rodata字符串,除非它短到4个字符,在这种情况下,它会被表示为一个int ...与-O2。

4

0 回答 0