Я пытаюсь реализовать очень простую функцию для печати строк в моем ядре.
Проблема кажется мне очень странной, и я думаю, что, возможно, пропустил что-то важное, но я понятия не имею, что.
Итак, у меня есть код, который не работает:
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
============= ============= EDIT
после исследований кажется, что mtrrs не поддерживаются с настройками qemu по умолчанию (я проверил это, используя определенные настройки процессора). Проверьте код здесь:
(Стоит отметить, что 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 устанавливает бит 30 в cr0, который, по утверждению Intel, должен отключить кеширование.
Это по-прежнему печатает первую букву, в то время как более короткая строка печатается нормально …
Я не знаю, что искать сейчас. Есть ли у вас какие-либо идеи ? Спасибо большое
============= ============= EDIT
Ничего себе, только что нашел хорошую ошибку …
Решение было в скрипте компоновщика:
.rodata BLOCK(4K) : ALIGN(4K) {
*(.rodata)
}
стали:
.rodata BLOCK(4K) : ALIGN(4K) {
*(.rodata*)
}
только потому, что лязг произвел меня не .rodata раздел, но вместо .rodata.str1.1 один.
Это приводило к отсутствию строки родата, если она не была такой короткой, как 4 символа, и в этом случае она оказалась бы представленной как int … с -O2.
Задача ещё не решена.