Задать вопрос
  • Что делать, на QEMU всё летает, а реальный Celeron D умирает?

    brar, если тебе так проще — можешь считать, что я попросил ИИ проанализировать чужой код. Только вот ни один ИИ сам по себе не полезет в репозиторий, не найдет там баг с присваиванием type = 0 вместо == в mouse_wait, не разберется в маскировке каскадного PIC и не заметит, что инициализация мыши вызывается до настройки IDT.

    Если у тебя есть, что сказать по существу проблемы (почему Celeron D умирает) — пиши. Если просто пришел написать "это нейросеть", то ты опоздал, этот билет уже кто-то пробил.
    Написано
  • Как выставить элементу ширину по содержимому при переносах?

    Да, это реально фундаментальная проблема CSS. Движок считает раскладку в один проход. Он видит, что контент шире 200px, сжимает блок до ширины родителя и переносит текст. Всё. Пересчитать ширину под самую длинную получившуюся строку он уже не может — для этого нужен итеративный алгоритм, который тупо убил бы производительность рендера.

    min-content тут не спасет, он разложит слова в столбик, отталкиваясь от самого длинного слова, а не от того, как текст реально перенесся.

    Сделать единую прямоугольную плашку на чистом CSS не выйдет. Единственное CSS-решение — скинуть фон с дива на инлайн-текст (span) и использовать box-decoration-break: clone. Но тогда фон будет рваться на каждой строке (как хайлайтер), а не быть цельным блоком.

    Если нужна именно цельная плашка, обрезанная по самой длинной строке, без JS не обойтись. Ты упоминал getBoundingClientRect(), но для многострочного текста он вернет ширину всего bounding box (то есть ширину родителя). Правильнее использовать Range и getClientRects() — этот метод возвращает массив прямоугольников для каждой строки текста. Остаётся только найти максимальную ширину и применить её к родителю.

    Примерно так:

    const child = document.querySelector('.child');
    const span = child.querySelector('span');
    
    // Создаем диапазон для текста внутри span
    const range = document.createRange();
    range.selectNodeContents(span);
    
    // Получаем прямоугольники для каждой строки текста
    const rects = range.getClientRects();
    let maxWidth = 0;
    
    for (let rect of rects) {
        if (rect.width > maxWidth) {
            maxWidth = rect.width;
        }
    }
    
    // Применяем ширину самой длинной строки к родителю
    child.style.width = `${Math.ceil(maxWidth)}px`;


    Это сработает на 100% и даст тот самый эффект, который тебе нужен.
    Написано
  • Что делать, на QEMU всё летает, а реальный Celeron D умирает?

    Тут сходится сразу несколько жестких багов:

    1. Главный убийца реального железа: баг в `mouse_wait`
    В файле `keyboard.c` у тебя написано:
    void mouse_wait (unsigned char type) {
    	if (type = 0) {
    		while ((inb(0x64) & 2) != 0);
    	} else {
    		while ((inb(0x64) & 1) == 0);
    	}
    }

    У тебя тут не сравнение `==`, а присваивание `=`. Выражение `type = 0` всегда возвращает `false` (ноль), поэтому функция **всегда** уходит в ветку `else` и крутит `while ((inb(0x64) & 1) == 0);`.
    То есть, когда ты вызываешь `mouse_wait(0)`, чтобы дождаться готовности контроллера к *записи*, система тупо ждет, пока в буфере не появятся данные на *чтение*. На реальном железе это убивает инициализацию мыши и клавы, вешает PIC и ломает прерывания таймера. Замени `type = 0` на `type == 0`.

    2. Почему пищалка ускоряется в 2 раза (APIC)
    Если у тебя в BIOS включен APIC, а ты используешь старый 8259 PIC, на новых процессорах прерывание от таймера может приходить дважды (один раз от APIC, второй от legacy PIC). В QEMU APIC обычно отключен или эмулируется иначе, а Celeron D может гонять прерывания дважды.
    Решение: отключи APIC в ядре. Запиши ноль в SVR (Spurious Interrupt Vector Register):
    `*(volatile unsigned int*)(0xFEE000F0) = 0;` перед инициализацией PIC.

    3. Почему мышь и время не отрисовываются (Маскировка PIC)
    В `idt.c` в функции `pic_remap` ты пишешь:
    `outb(0x21, 0xFC);` (в бинарте это `11111100`).
    Ты размаскировал только IRQ0 (таймер) и IRQ1 (клава). Но бит 2 (IRQ2) остался замаскированным!
    IRQ2 — это каскадный канал, который соединяет Slave и Master PIC. Мышь висит на IRQ12 (Slave PIC). Поскольку IRQ2 замаскирован, прерывания от мыши тупо не доходят до процессора!
    Нужно писать `outb(0x21, 0xF8);` (`11111000`), чтобы открыть IRQ2. А на Slave PIC (`0xA1`) нужно написать `0xEF` (`11101111`), чтобы открыть IRQ12.

    4. Почему отваливается клавиатура (Переполнение буфера)
    В `keyboard_handler_c` ты читаешь только один байт: `current_scancode = inb(0x60);`.
    На реальном железе при быстром нажатии или удержании клавиши контроллер генерирует несколько сканкодов подряд. Если ты не вычитываешь их все из порта 0x60, буфер контроллера переполняется, он ставит флаг ошибки и блокирует шину. Клава умирает, пока ты не сделаешь сброс.
    Нужно читать в цикле:
    void keyboard_handler_c(void) {
        while (inb(0x64) & 1) { // Читаем, пока есть данные
            current_scancode = inb(0x60);
            kbd_ready = 1;
        }
        outb(0x20, 0x20);
    }


    5. Порядок инициализации
    В `kernel.c` у тебя:
    `mouse_init();` вызывается **до** `idt_init();`.
    `mouse_init` включает прерывания мыши на контроллере. Если мышь в этот момент дернется, она сгенерирует IRQ, а IDT еще не настроен. Процессор улетит в Stage 2 или получит General Protection Fault. Перенеси `mouse_init()` строго **после** `idt_init()`. А вообще лучше вызывать инициализацию мыши уже после того, как прерывания включены (`sti`), иначе ты блокируешь таймер во время долгих циклов ожидания мыши.

    Что чинить прямо сейчас:
    1. Исправь `type = 0` на `type == 0` в `keyboard.c`.
    2. Замени маски PIC на `0xF8` и `0xEF`.
    3. Вычитывай клаву в цикле внутри ISR.
    4. Поменяй местами `mouse_init` и `idt_init`.
    Написано
  • Как выставить элементу ширину по содержимому при переносах?

    Alexandroppolus, Да, это фундаментальная засада CSS. Движок считает ширину в один проход. Он видит, что контент шире 200px, сжимает чилд до доступной ширины парента и переносит текст. А вот потом сжаться под длину самой длинной строки он уже не может, потому что для этого нужен итеративный пересчет, которого в CSS нет.

    inline-block и table тут не спасут, они отдают приоритет доступной ширине родителя, если контент не влезает.

    Единственный рабочий CSS-костыль для этого - float: left. Флоаты исторически считали ширину иначе: берут max-content, если он влезает, либо сжимаются до доступной ширины, переносят текст и схлопываются до самой длинной строки.
    .child {
      float: left;
      background: green;
      font-size: 30px;
      border-radius: 14px;
    }

    Только паренту не забудь добавить overflow: hidden или классический clearfix, потому что флоат выпадает из потока.
    Написано