os dev: vga печать строк и странное поведение компилятора

Я пытаюсь реализовать очень простую функцию для печати строк в моем ядре.

Проблема кажется мне очень странной, и я думаю, что, возможно, пропустил что-то важное, но я понятия не имею, что.

Итак, у меня есть код, который не работает:

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.

0

Решение

Задача ещё не решена.

Другие решения


По вопросам рекламы [email protected]