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

=============編集=============

調査の結果、mtrrs はデフォルトの qemu 設定ではサポートされていないようです (特定の 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 を設定することです。これは、Intel が主張するキャッシュを無効にすることです。これでも最初の文字が出力されますが、短い文字列は正常に出力されます...

今何を調べたらいいのかわからない。何か考えはありますか?本当にありがとうございました

=============編集=============

うわー、ちょうどいいバグを見つけた...

解決策はリンカースクリプトにありました:

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

なりました:

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

clang が.rodataセクションではなく.rodata.str1.1セクションを生成したからです。これにより、rodata 文字列が 4 文字と短い場合を除き、rodata 文字列が欠落していました。その場合、-O2 を使用すると int... として表されます。

4

0 に答える 0