Jak komputery wyświetlają surowy tekst i grafikę niskiego poziomu

46

Moje stale rosnące zainteresowanie komputerami zmusza mnie do zadawania głębszych pytań, na które wydaje się, że nie musimy już więcej zadawać. Nasze komputery, podczas rozruchu, o ile rozumiem, są w trybie tekstowym , w którym znak może być wyświetlany za pomocą przerwania oprogramowania, 0x10gdy AH=0x0e. Wszyscy widzieliśmy słynną czcionkę rozruchową, która zawsze wygląda tak samo, niezależnie od tego, który komputer się uruchamia.

Jak więc, u licha, komputery generują grafikę na najniższym poziomie, powiedzmy, poniżej systemu operacyjnego? A także, na pewno grafika nie jest generowana piksel na raz za pomocą przerwań programowych, ponieważ to brzmi bardzo wolno?

Czy istnieje standard definiujący podstawowe wyprowadzanie wierzchołków, wielokątów, czcionek itp. (Na przykład poniżej OpenGL, którego może używać OpenGL)? Pytam, dlaczego system operacyjny często może działać bez oficjalnych sterowników; jak oni to robią?

Przepraszam, jeśli moje założenia są błędne. Byłbym bardzo wdzięczny za opracowanie na te tematy!

Doddy
źródło
To nie wszystkie komputery, to zależy od sprzętu wyświetlającego. Komputery oparte na linii ewolucyjnej IBM pierwotnie miały tylko tryb tekstowy, a następnie dodano różne tryby graficzne. Wciąż mamy tę spuściznę. Starsze komputery często miały tylko tryb tekstowy. Inne komputery miały tylko tryby graficzne, takie jak Amiga i oryginalne Macintoshes.
hippietrail

Odpowiedzi:

25

To (częściowo) rola systemu BIOS.

Podstawowy system wyjściowy komputera odpowiada za zapewnienie wspólnego interfejsu dla systemów operacyjnych, pomimo różnic między rzeczywistymi komputerami.

To powiedziawszy, w przypadku grafiki istnieją różne sposoby rysowania na ekranie. Istnieją polecenia TTY, które można wysłać do BIOS-u, ale działa to tylko w trybie rzeczywistym. Jeśli chcesz narysować cokolwiek w trybie chronionym, musisz użyć VGA do rysowania. Nie potrafię tego wyjaśnić lepiej niż OSDev, więc spójrz tutaj, aby uzyskać więcej informacji - ale w zasadzie możesz pisać do pamięci (pamięć wideo jest odwzorowana w pamięci), zaczynając od adresu, 0xB8000aby rysować rzeczy na ekranie.

Jeśli potrzebujesz wyższej rozdzielczości niż VGA, musisz użyć rozszerzeń VESA BIOS; Nie znam go, ale spróbuj poszukać kodu źródłowego GRUB, aby uzyskać więcej informacji.

Kilka przydatnych odniesień:


Jeśli znasz D - napisałem jakiś program ładujący jakiś czas temu, który był w stanie napisać na ekranie (tylko tekst). Jeśli jesteś zainteresowany, oto kod:

align(2) struct Cell { char ch; ubyte flags = 0x07; }

@property Cell[] vram()
{ return (cast(Cell*)0xB8000)[0 .. CONSOLE_WIDTH * CONSOLE_HEIGHT]; }

void putc(char c)
{
    if (isBochs) { _outp(0xE9, c); }  // Output to the Bochs terminal!

    bool isNewline = c == '\n';
    while (cursorPos + (isNewline ? 0 : 1) > vram.length)
    {
        for (short column = CONSOLE_WIDTH - 1; column >= 0; column--)
        {
            foreach (row; 0 .. CONSOLE_HEIGHT - 1)
            {
                uint cell = column + cast(uint)row * CONSOLE_WIDTH;
                vram[cell] = vram[cell + CONSOLE_WIDTH];
            }
            vram[column + (CONSOLE_HEIGHT - 1) * CONSOLE_WIDTH].ch = ' ';
        }
        cursorPos = cast(ushort)(cursorPos - CONSOLE_WIDTH);
    }
    if (isNewline)
        cursorPos = cast(ushort)
            ((1 + cursorPos / CONSOLE_WIDTH) * CONSOLE_WIDTH);
    else vram[cursorPos++].ch = c;
}

void putc(char c, ubyte attrib) { vram[cursorPos] = Cell(c, attrib); }

void memdump(void* pMem, size_t length)
{
    foreach (i; 0 .. length)
        putc((cast(char*)pMem)[i]);
}

void clear(char clear_to = '\0', ubyte attrib = DEFAULT_ATTRIBUTES)
{
    foreach (pos; 0 .. vram.length)
        vram[pos] = Cell(clear_to, attrib);
    cursorPos = 0;
}

@property ushort cursorPos()
{
    ushort result = 0;
    _outp(0x3D4, 14);
    result += _inp(0x3D5) << 8;
    _outp(0x3D4, 15);
    result += _inp(0x3D5);
    return result;
}

@property void cursorPos(ushort position)
{
    _outp(0x3D4, 14);
    _outp(0x3D5, (position >> 8) & 0xFF);
    _outp(0x3D4, 15);
    _outp(0x3D5, position & 0xFF);
}
Mehrdad
źródło
Dziękuję za odpowiedź. Dlaczego kod źródłowy GRUB? Nie wiedziałem, że GRUB jest związany z samą grafiką.
Doddy
2
@panic Grub2 może robić kilka interesujących rzeczy, w tym wyświetlanie obrazu jako tła w menu wyboru systemu operacyjnego. Nie jestem pewien co do gruba.
Izkata
@panic: Nie jestem pewien, czy jest to GRUB, czy GRUB2 (ogólnie użyłem „GRUB”), ale zdecydowanie mogą one zmienić na natywną rozdzielczość 1600x900 na moim monitorze, więc jestem pewien, że będą mieć rzeczy, które możesz obejrzeć. (Przyglądałem się im jakiś czas temu i pamiętam, że były one pomocne, ale minęło trochę czasu, więc nie pamiętam dokładnie, w których plikach powinieneś zajrzeć.)
Mehrdad
czy termin ten memory-mappedoznacza, że ​​w pamięci RAM znajduje się obszar „bufora”, w którym procesor (lub czy istnieje inna jednostka DMA?) może odczytywać i zapisywać zarówno w imieniu karty graficznej, jak i programu, który próbuje zapisać na wyświetlaczu?
n611x007
1
@naxa: Dobre pytanie ... zwykle sprzęt zmapowany w pamięci oznacza, że ​​w pamięci znajduje się adres, który w rzeczywistości nie odpowiada pamięci RAM. Raczej czytanie lub pisanie na nim odpowiada wykonaniu pewnej akcji na jakimś sprzęcie. To powiedziawszy, nie jestem pewien, jak można odróżnić rzeczywistą pamięć RAM od sprzętu, który sprawia, że ​​blok pamięci wygląda jak RAM ... może być tak, że w tym przypadku jest to rzeczywista pamięć RAM, ale miałem wrażenie, że przechwytywanie odczytu i zapisu jest przechwytywane według sprzętu.
Mehrdad
25

Od samego początku komputera IBM i jego klonów sprzęt karty graficznej był bardzo prosty: mały blok pamięci był dedykowany siatce komórek znakowych (80 x 25 znaków w trybie standardowym), z dwoma bajtami pamięci dla każdej komórki . Jeden bajt wybrał znak, a drugi „atrybuty” - kolory pierwszego planu i tła oraz sterowanie miganiem dla kart kolorów; pogrubione, podkreślone, migające lub odwrócone wideo dla adapterów monochromatycznych. Sprzęt wyszukiwał piksele z tabeli ROM kształtów znaków zgodnie z zawartością pamięci znaków.

Aby zapewnić pewien stopień niezależności sprzętowej, interfejs BIOS-u do mapy znaków wymagał wykonania przerwania programowego w celu ustawienia pojedynczej komórki znakowej na ekranie. To było powolne i nieefektywne. Pamięć znaków była jednak również adresowalna bezpośrednio przez CPU, więc jeśli wiesz, jaki sprzęt był obecny, możesz zamiast tego pisać bezpośrednio do pamięci. Tak czy inaczej, po ustawieniu, postać pozostanie na ekranie, dopóki nie zostanie zmieniona, a całkowita pamięć znaków, z którą trzeba pracować, to 4000 bajtów - mniej więcej tyle, co rozmiar pojedynczej pełnokolorowej tekstury 32 x 32!

W trybach graficznych sytuacja była podobna; każdy piksel na ekranie jest powiązany z określoną lokalizacją w pamięci, a interfejs BIOS-piksel był ustawiony, ale praca z wysoką wydajnością wymagała zapisu bezpośrednio do pamięci. Późniejsze standardy, takie jak VESA, pozwalają systemowi wykonać kilka wolnych zapytań opartych na systemie BIOS, aby poznać układ pamięci urządzenia, a następnie pracować bezpośrednio z pamięcią. W ten sposób system operacyjny może wyświetlać grafikę bez wyspecjalizowanego sterownika, chociaż współczesne systemy operacyjne zawierają również podstawowe sterowniki dla wszystkich głównych producentów układów GPU. Nawet najnowsza karta NVidia będzie obsługiwać kilka różnych trybów kompatybilności wstecznej, prawdopodobnie aż do IBM CGA.

Jedną ważną różnicą między grafiką 3D a 2D jest to, że w 2D generalnie nie trzeba przerysowywać całego ekranu co klatkę. W 3D, jeśli kamera porusza się choć trochę, każdy piksel na ekranie może się zmienić; w 2D, jeśli nie przewijasz, większość ekranu pozostanie niezmieniona klatka po klatce, a nawet jeśli przewijasz, ogólnie możesz wykonać szybką kopię z pamięci do pamięci zamiast ponownie komponować całą scenę. Nie ma więc nic przeciwko wykonywaniu INT 10h dla każdego piksela każdej klatki.

Źródło: Jestem naprawdę stary

Russell Borogove
źródło
Bardzo pouczające, dzięki. Chciałbym móc zaakceptować więcej niż jeden!
Doddy,
8

Podczas rozruchu system BIOS szuka karty wideo. W szczególności szuka wbudowanego programu BIOS karty wideo i uruchamia go. Ten BIOS zwykle znajduje się w pamięci C000h. Systemowy BIOS wykonuje BIOS wideo , który inicjuje kartę wideo.

To, które poziomy lub tryby wideo / grafiki może wyświetlać natywnie BIOS, bez systemu operacyjnego lub sterowników, zależy przede wszystkim od samego BIOS-u wideo.

Źródło / Więcej informacji tutaj - „System Boot Sequence”

Ƭᴇcʜιᴇ007
źródło
6

Nasze komputery podczas rozruchu, o ile rozumiem, są w trybie tekstowym, w którym znak może być wyświetlany za pomocą przerwania programowego 0x10, gdy AH = 0x0e

Mówisz o starszych funkcjach systemu BIOS. W rzeczywistości nie musisz wcale korzystać z takich funkcji. Zapisujesz je bezpośrednio w pamięci wideo.

jak, u licha, komputery generują grafikę na najniższym poziomie, powiedzmy, poniżej systemu operacyjnego?

Ma to silnie związek z działaniem systemu operacyjnego. W każdym razie operacja jest taka sama na poziomie sprzętowym: karta wideo ma wideo RAM, która przechowuje (upraszcza) następny obraz do narysowania na ekranie. Możesz pomyśleć, że każdy adres jest bajtem reprezentującym piksel (w zasadzie potrzebujesz więcej niż jednego bajtu na piksel). Następnie kontroler wideo zajmuje się przekształceniem tego sygnału na sygnał zrozumiały dla monitora.

Czy istnieje standard definiujący podstawowe wyprowadzanie wierzchołków, wielokątów, czcionek itp. (Na przykład poniżej OpenGL, którego może używać OpenGL)?

AFAIK, nr Nie ma norm dotyczących logicznych reprezentacji graficznych.

Pytam, dlaczego system operacyjny często może działać bez oficjalnych sterowników; jak oni to robią?

Ponieważ ma już sterowniki dołączone do systemu operacyjnego.

m0skit0
źródło