Как я могу написать прямо на экран? - PullRequest
20 голосов
/ 04 января 2011

Я подросток, который очень заинтересовался языком ассемблера.Я пытаюсь написать небольшую операционную систему на ассемблере Intel x86, и мне было интересно, как писать прямо на экран, не полагаясь на BIOS или другие операционные системы.Я просматривал источники coreboot, Linux и Kolibri, в частности, в надежде найти и понять какой-то фрагмент кода, который делает это.Я пока не преуспел в этом, хотя я полагаю, что я еще раз взгляну на исходный код Linux, поскольку он является наиболее понятным для меня из источников, которые я искал.

Если кто-нибудь знает это, или знает, где в каком-то фрагменте исходного кода я мог бы посмотреть, я был бы признателен, если бы мне сказали.

Или еще лучше, если кто-то знает, как определить, какой порт ввода-вывода на Intel x86Процессор подключается к тому или иному аппаратному обеспечению, что также будет оценено.Причина, по которой я должен спросить об этом, состоит в том, что ни в главе для ввода / вывода в Руководстве разработчика программного обеспечения Intel 64 и IA-32, том 1: Базовая архитектура, ни в разделах, посвященных инструкции IN или OUT в томе 3,Могу ли я найти любую из этой информации.И потому что было слишком трудно искать соответствующие инструкции в источниках, которые у меня есть.

Ответы [ 7 ]

18 голосов
/ 04 января 2011

ЧАСТЬ 1

Для старых режимов VGA существует фиксированный адрес для записи в (унаследованную) область памяти дисплея. Для текстовых режимов эта область начинается с 0x000B8000. Для графических режимов он начинается с 0x000A0000.

Для режимов видео высокого разрешения (например, настроенных интерфейсом VESA / VBE) это не работает, потому что размер устаревшей области памяти дисплея ограничен 64 КиБ, а большинству режимов видео высокого разрешения требуется намного больше места (например, 1024 * 768 * 32-bpp = 2,25 МиБ). Чтобы обойти это, есть 2 различных метода, поддерживаемых VBE.

Первый метод называется «переключение банков», когда только часть отображаемой памяти видеокарты в любое время отображается в прежнюю область (и вы можете изменить, какая часть отображается). Это может быть довольно запутанным - например, чтобы нарисовать один пиксель, вам может понадобиться вычислить, в каком банке находится пиксель, затем переключиться на этот банк, а затем вычислить, какое смещение в банке. Что еще хуже, для некоторых режимов видео (например, для режимов видео 24 бит / с, где 3 пикселя на пиксель) только первая часть данных пикселя может находиться в одном банке, а вторая часть данных того же пикселя - в другом банке , Основным преимуществом этого является то, что он работает с адресацией в реальном режиме, так как область памяти устаревшего дисплея ниже 0x00100000.

Второй метод называется «Linear Framebuffer» (или просто «LFB»), где вся область памяти видеокарты может быть доступна без какого-либо беспорядочного переключения банков. Вы должны спросить интерфейс VESA / VBE, где находится эта область (и обычно она находится в «дыре PCI» где-то между 0xC0000000 и 0xFFF00000). Это означает, что вы не можете получить к нему доступ в реальном режиме, и вам нужно использовать защищенный режим или длинный режим или «нереальный режим».

Чтобы найти адрес пикселя при использовании режима LFB, вам нужно сделать что-то вроде «pixel_address = display_memory_address + y * bytes_per_line + x * bytes_per_pixel». «Bytes_per_line» происходит из интерфейса VESA / VBE (и может отличаться от «horizontal_resolution * bytes_per_line», поскольку между горизонтальными линиями может быть заполнение).

Для режимов VBE / VESA с "банковским переключением" это выглядит примерно так:

pixel_offset = y * bytes_per_line + x * bytes_per_pixel;
bank_number = pixel_offset / bank_size;
pixel_starting_address_within_bank = pixel_offset % bank_size;

Для некоторых старых режимов VGA (например, 256-цветный «режим 0x13») он очень похож на LFB, за исключением того, что между строками нет отступов, и вы можете сделать «pixel_address = display_memory_address + (y * horizontal_resolution + x) * bytes_per_pixel ». Для текстовых режимов это в основном одно и то же, за исключением того, что 2 байта определяют каждый символ и его атрибут - например, msgstr "char_address = display_memory_address + (y * Horizontal_resolution + x) * 2". Для других старых режимов VGA (монохромный / 2-цветный, 4-цветный и 16-цветный режимы) память видеокарты расположена совершенно иначе. Он разделен на «плоскости», где каждая плоскость содержит один бит пикселя, и (например, для обновления одного пикселя в 16-цветном режиме вам необходимо записать в 4 отдельные плоскости). По соображениям производительности аппаратное обеспечение VGA поддерживает разные режимы записи и разные режимы чтения, и это может стать сложным (слишком сложным, чтобы адекватно описывать его здесь).

ЧАСТЬ 2

Для портов ввода / вывода (для 80x86, «Совместимые с ПК») есть 3 основные категории. Первый - это «стандартные де-факто» устаревшие устройства, которые используют фиксированные порты ввода / вывода. Сюда входят такие вещи, как микросхемы PIC, контроллер ISA DMA, контроллер PS / 2, микросхема PIT, последовательные / параллельные порты и т. Д. Почти все, что описывает, как программировать каждое из этих устройств, скажет вам, какие порты ввода / вывода использует устройство.

Следующая категория - это устаревшие / ISA-устройства, где используемые порты ввода-вывода определяются перемычками на самой плате, и нет никакого разумного способа определить, какие порты ввода-вывода они используют из программного обеспечения. Чтобы обойти это, конечный пользователь должен сообщить ОС, какие порты ввода / вывода использует каждое устройство. К счастью, все это стало устаревшим (хотя это не обязательно означает, что никто не использует его).

Третья категория - «подключи и работай», где есть какой-то метод запроса устройства, какие порты ввода / вывода оно использует (и в большинстве случаев изменение портов ввода / вывода, которые использует устройство). Примером этого является PCI, где есть «пространство конфигурации PCI», которое сообщает вам много информации о каждом устройстве PCI. Для этих категорий никто не может определить, какие устройства будут использовать какие порты ввода / вывода, не делая этого во время выполнения, и изменение некоторых настроек BIOS может привести к тому, что любое / все эти устройства изменят порты ввода / вывода.

Также обратите внимание, что процессор Intel - это только процессор. Ничто не мешает использовать эти процессоры в чем-то, что радикально отличается от «ПК-совместимого» компьютера. Руководства по процессорам Intel никогда не расскажут вам об оборудовании, которое существует за пределами самого процессора (включая чипсет или устройства).

часть 3

Вероятно, лучшее место для получения дополнительной информации (предназначенной для разработчиков ОС / любителей) - http://osdev.org/ (их вики и их форумы).

1 голос
/ 13 августа 2017

Для прямой записи на экран вам, вероятно, следует записать в область VGA Text Mode. Это блок памяти, который является буфером для текстового режима.

Экран текстового режима состоит из 80x25 символов; каждый символ имеет ширину 16 бит. Если первый бит установлен, символ будет мигать на экране. Следующие 3 бита детализируют цвет фона; последние 4 бита первого байта являются цветом переднего плана (или текстового символа). Следующие 8 битов являются значением символа. Обычно это кодовая страница 737 или 437, но она может варьироваться от системы к системе.

Здесь - это страница Википедии с подробным описанием этого буфера, а здесь - ссылка на кодовую страницу 437

.

Почти все BIOS устанавливают текстовый режим до загрузки системы, но некоторые BIOS ноутбуков не загружаются в текстовом режиме. Если вы еще не в текстовом режиме, вы можете установить его с помощью int10h очень просто:

xor ah, ah
mov al, 0x03
int 0x10

(В приведенном выше коде используются прерывания BIOS, поэтому его нужно запускать в реальном режиме. Я рекомендую поместить это в свой загрузочный сектор.)

Наконец, вот набор подпрограмм, которые я написал для написания строк в защищенном режиме.

unsigned int terminalX;
unsigned int terminalY;
uint8_t terminalColor;
volatile uint16_t *terminalBuffer;

unsigned int strlen(const char* str) {
    int len;
    int i = 0;
    while(str[i] != '\0') {
        len++;
        i++;
    }
    return len;
}

void initTerminal() {
    terminalColor = 0x07;
    terminalBuffer = (uint16_t *)0xB8000;
    terminalX = 0;
    terminalY = 0;

    for(int y = 0; y < 25; y++) {
        for(int x = 0; x < 80; x++) {
            terminalBuffer[y * 80 + x] = (uint16_t)terminalColor << 8 | ' ';
        }
    }
}

void setTerminalColor(uint8_t color) {
    terminalColor = color;
}

void putCharAt(int x, int y, char c) {
    unsigned int index = y * 80 + x;
    if(c == '\r') {
        terminalX = 0;  
    } else if(c == '\n') {
        terminalX = 0;
        terminalY++;
    } else if(c == '\t') {
        terminalX = (terminalX + 8) & ~(7);
    } else {
        terminalBuffer[index] = (uint16_t)terminalColor << 8 | c;
        terminalX++;
        if(terminalX == 80) {
            terminalX = 0;
            terminalY++;
        }
    }
}

void writeString(const char *data) {
    for(int i = 0; data[i] != '\0'; i++) {
        putCharAt(terminalX, terminalY, data[i]);       
    }           
}

Вы можете прочитать об этом на этой странице .

1 голос
/ 04 января 2011

Для обычных портов ввода / вывода вы должны пройти через BIOS, что означает прерывания. Много синих лун назад я использовал ссылки из Дона Стонера , чтобы помочь написать какую-то сборку в реальном режиме, но я перегорел на ней через несколько месяцев и забыл большую часть того, что знал.

1 голос
/ 04 января 2011

Это не так просто. Хотя BIOS предоставляет INT 10h для записи текста на экран, графика отличается от одного адаптера к другому. Например, вы можете найти информацию для VGA http://www.wagemakers.be/english/doc/vga здесь. Некоторые древние SVGA адаптеры http://www.intel -assembler.it / portale / 5 / сборка-энциклопедия программирования игр / сборка-программирование-игры-энциклопедия.asp здесь.

1 голос
/ 04 января 2011

Немного за пределами моей компетенции, но вы можете посмотреть на VESA .

0 голосов
/ 16 января 2011

Я нашел книгу, которая, кажется, отвечает на мои вопросы.Я понял, что такая книга может существовать после прочтения об этом на странице FreeVGA.Вот ссылка: Руководство программиста по картам EGA, VGA и Super VGA

0 голосов
/ 05 января 2011

Я нашел место, где можно найти хорошую информацию по этому вопросу: http://www.osdever.net/FreeVGA/home.htm В нем говорится о некоторых деталях, важных для написания кода, который пишет прямо на экран. Я нашел это по ссылке на сайт Дона Стонера (спасибо за ссылку, SilverbackNet!). Я все еще ищу больше информации, поэтому, если у кого-то есть еще идеи, я очень признателен за помощь.

...