web-dev-qa-db-ja.com

コンピュータが生の低レベルのテキストとグラフィックを表示する方法

コンピュータへの関心がますます高まっているため、私はより深い質問をするようになり、もう質問する必要がないようです。私たちのコンピューターは、私が理解している限り、起動時に テキストモード にあり、ソフトウェア割り込みを使用して文字を表示できます 0x10 の場合 AH=0x0e 。どのコンピューターがブートしているかに関係なく、常に同じに見える有名なブートフォントを見てきました。

それでは、コンピュータはどのようにして、たとえばOSよりも低いレベルでグラフィックスを出力するのでしょうか。また、ソフトウェアの割り込みを使用してグラフィックが一度に1ピクセルずつ出力されないことは確かです。

頂点、ポリゴン、フォントなどの基本的な出力を定義する標準はありますか(OpenGLの下など、どのOpenGLが使用する可能性がありますか)?私が尋ねるのは、公式のドライバーがインストールされていなくてもOSが問題ないことが多い理由です。彼らはそれをどのように行うのですか?

私の仮定が正しくない場合の謝罪。これらのトピックについて詳しく説明していただければ幸いです。

46
Doddy

これが(部分的に)BIOSの役割です。

コンピュータの基本入出力システムは、実際のコンピュータ間のこのような違いにもかかわらず、オペレーティングシステムへの共通インターフェースを提供する責任があります。

とはいえ、具体的にはグラフィックスの場合、画面に描画する方法はいくつかあります。 BIOSに送信できるTTYコマンドがありますが、それはリアルモードでのみです。プロテクトモードで何かを描画する場合は、VGAを使用して描画する必要があります。 OSDevよりよく説明できないので、 詳細はこちら -を見てください。ただし、基本的には、アドレス0xB8000からメモリに書き込むことができます(ビデオメモリはメモリマップされています)。画面に物を描いてください。

VGAよりも高い解像度が必要な場合は、VESA BIOS拡張機能を使用する必要があります。私はそれに慣れていませんが、詳細についてはGRUBソースコードを参照してください。

いくつかの有用な参照:


あなたがたまたまDに精通しているのであれば、私はしばらく前に画面に書き込むことができる小さなブートローダーを書きました(テキストのみ)。興味があるなら、ここにコードがあります:

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);
}
25
user541686

IBM PCとそのクローンの初期の頃から、ディスプレイアダプタのハードウェアは非常にシンプルでした。小さなメモリブロックが文字セルのグリッド(標準モードでは80x25文字)専用で、各セルに2バイトのメモリが搭載されていました。 。 1バイトは文字を選択し、もう1バイトはその「属性」を選択しました-前景色と背景色、およびカラーアダプターの点滅コントロール。モノクロアダプタの太字、下線付き、点滅、または反転のビデオ。ハードウェアは、文字メモリの内容に従って、文字形状のROMテーブルからピクセルを検索しました。

ハードウェアにある程度の独立性を提供するために、文字マップへのBIOSインターフェイスでは、画面に単一の文字セルを設定するためにソフトウェア割り込みを実行する必要がありました。これは遅く、非効率的でした。ただし、文字メモリはCPUからも直接アドレス指定できるため、存在するハードウェアがわかっている場合は、代わりにメモリに直接書き込むことができます。どちらの方法でも、一度設定すると、キャラクターは変更されるまで画面上に残り、作業に必要な合計キャラクターメモリは4000バイトでした。これは、単一の32x32フルカラーテクスチャのサイズとほぼ同じです。

グラフィックモードでは、状況は似ていました。画面上の各ピクセルはメモリ内の特定の場所に関連付けられており、BIOSセットピクセルインターフェイスがありましたが、高性能の作業にはメモリへの直接書き込みが必要でした。 VESAのような後の標準では、システムはBIOSベースのクエリをいくつか実行してハードウェアのメモリレイアウトを学習し、メモリを直接操作します。これは、OSが特別なドライバーなしでグラフィックを表示できる方法ですが、最新のOSには、すべての主要なGPUメーカーのハードウェア用の基本的なドライバーも含まれています。最新のNVidiaカードでさえ、おそらくIBM CGAにまで遡って、いくつかの異なる下位互換性モードをサポートします。

3Dグラフィックスと2Dの重要な違いの1つは、2Dでは通常、フレームごとに画面全体を再描画する必要がないことです。 3Dでは、カメラが少しでも動くと、画面上のすべてのピクセルが変化する可能性があります。 2Dでは、スクロールしていない場合、画面の大部分はフレーム間で変更されません。スクロールしている場合でも、通常は、シーン全体を再構成する代わりに、メモリ間の高速コピーを実行できます。したがって、フレームごとにすべてのピクセルに対してINT 10hを実行する必要はありません。

出典:私は本当に年をとっています

25

ブート中にシステム [〜#〜] bios [〜#〜] はビデオアダプタを探します。特に、ビデオアダプターの組み込みBIOSプログラムを探して実行します。このBIOSは通常、メモリのC000hにあります。システムBIOSは ビデオBIOS を実行し、ビデオアダプターを初期化します。

BIOSがOSまたはドライバーなしでネイティブに表示できるビデオ/グラフィックスのレベルまたはモードは、主にビデオBIOS自体に依存します。

ソース/詳細はこちら -"システムブートシーケンス"

8

私たちのコンピューターは、ブート時、私が理解している限り、テキストモードになっています。このモードでは、AH = 0x0eのときにソフトウェア割り込み0x10を使用して文字を表示できます。

あなたはレガシーBIOS機能について話しています。実際、そのような関数を使用する必要はまったくありません。ビデオメモリに直接書き込みます。

コンピュータはどのようにして、たとえばOSよりも低いレベルでグラフィックスを出力するのでしょうか。

これは、OSの動作に強く関係しています。とにかく、操作はハードウェアレベルでも同じです。ビデオカードにはビデオRAMがあり、画面に描画される次のイメージを格納(簡略化)します。各アドレスは、ピクセルを表すバイトであると考えることができます(実際には、通常、ピクセルごとに複数のバイトが必要です)。次に、ビデオコントローラーがこれをモニターが理解できる信号に変換します。

頂点、ポリゴン、フォントなどの基本的な出力を定義する標準はありますか(OpenGLの下など、どのOpenGLが使用する可能性がありますか)?

AFAIK、いいえ。論理的なグラフィック表現に関する標準はありません。

私が尋ねるのは、公式のドライバーがインストールされていなくてもOSが問題ないことが多い理由です。彼らはそれをどのように行うのですか?

すでにOSにバンドルされているドライバーがあるからです。

6
m0skit0