컴퓨터가 로우 레벨의 텍스트 및 그래픽을 표시하는 방법


46

컴퓨터에 대한 관심이 계속 높아지면서 더 이상 질문 할 필요가없는 더 깊은 질문을합니다. 우리 컴퓨터는 부팅 할 때 내가 이해하는 한 텍스트 모드 에 있으며 0x10언제 소프트웨어 인터럽트를 사용하여 문자를 표시 할 수 있습니다 AH=0x0e. 우리는 컴퓨터 부팅에 관계없이 항상 같은 모양의 유명한 부팅 글꼴을 보았습니다.

그렇다면 어떻게 컴퓨터가 OS보다 낮은 수준에서 그래픽을 출력합니까? 또한 소프트웨어 인터럽트를 사용하여 그래픽이 한 번에 한 픽셀 씩 출력되지 않습니다.

꼭짓점, 다각형, 글꼴 등의 기본 출력을 정의하는 표준이 있습니까 (예 : OpenGL에서 사용하는 OpenGL 아래)? 공식 드라이버를 설치하지 않고 OS를 사용할 수있는 이유는 무엇입니까? 그들은 어떻게합니까?

내 가정이 틀렸다면 사과드립니다. 이 주제에 대해 자세히 설명해 주셔서 감사합니다.


모든 컴퓨터가 아니라 디스플레이 하드웨어에 따라 다릅니다. IBM의 혁신적인 라인 기반 PC에는 원래 텍스트 모드 만 있었으며 다양한 그래픽 모드가 추가되었습니다. 우리는 여전히 그 유산을 가지고 있습니다. 오래된 컴퓨터에는 종종 텍스트 모드 만있었습니다. 다른 컴퓨터에는 Amiga 및 원래 Macintosh와 같은 그래픽 모드 만 있습니다.
hippietrail

답변:


25

그것이 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);
}

답변 해주셔서 감사합니다. 왜 GRUB 소스 코드입니까? GRUB이 그래픽 자체와 관련이 있다는 것을 몰랐습니다.
Doddy

2
@panic Grub2는 OS 선택 메뉴에서 이미지를 배경으로 표시하는 것을 포함하여 몇 가지 흥미로운 작업을 수행 할 수 있습니다. 그럽에 대해 확신이 없다.
이즈 카타

@panic : GRUB 또는 GRUB2 (일반적으로 "GRUB"를 사용)인지 확실하지 않지만 모니터에서 기본 1600x900 해상도로 확실히 전환 할 수 있으므로 볼 수있는 것이있을 것입니다. (나는 그들을 되돌아 보았고, 그들이 도움이되었다는 것을 기억하지만,
한참

이 용어 memory-mapped는 RAM에 CPU (또는 다른 DMA 장치가 있습니까?)가 그래픽 카드와 디스플레이에 쓰려고하는 프로그램을 대신하여 읽고 쓸 수있는 "버퍼"영역이 있음을 의미합니까?
n611x007

1
@naxa : 좋은 질문입니다. 일반적으로 메모리 매핑 하드웨어는 실제로 RAM에 해당하지 않는 주소가 메모리에 있음을 의미합니다. 오히려, 읽거나 쓰는 것은 일부 하드웨어에서 작업을 수행하는 것에 해당합니다. 즉, 메모리 블록을 RAM처럼 보이게 하는 실제 RAM과 하드웨어를 어떻게 구별 할 수 있는지 잘 모르겠습니다 .이 경우 실제 RAM 일 수 있습니다. 그러나 내 인상은 읽기와 쓰기가 차단된다는 것입니다. 하드웨어에 의해.
Mehrdad

25

IBM PC 및 클론의 초기부터 디스플레이 어댑터 하드웨어는 매우 간단했습니다. 작은 메모리 블록이 각 셀에 2 바이트의 메모리를 가진 문자 셀 그리드 (표준 모드에서 80x25 자)에 전용되었습니다. . 한 바이트는 문자를 선택하고 다른 바이트는 "속성"을 선택했습니다. 전경색 및 배경색과 색상 어댑터의 깜박임 제어. 단색 어댑터의 경우 굵은 체, 밑줄, 깜박임 또는 반전 비디오. 하드웨어는 문자 메모리의 내용에 따라 문자 모양의 ROM 테이블에서 픽셀을 조회했습니다.

어느 정도의 하드웨어 독립성을 제공하기 위해 문자표에 대한 BIOS 인터페이스는 화면에서 단일 문자 셀을 설정하기 위해 소프트웨어 인터럽트를 실행해야했습니다. 이것은 느리고 비효율적이었습니다. 그러나 문자 메모리도 CPU에서 직접 주소를 지정할 수 있으므로 어떤 하드웨어가 있는지 알고 있으면 대신 메모리에 직접 쓸 수 있습니다. 어느 쪽이든, 일단 설정되면, 문자는 변경 될 때까지 화면에 남아 있으며 작업에 필요한 총 문자 메모리는 4000 바이트였습니다. 이는 단일 32x32 풀 컬러 텍스처의 크기에 관한 것입니다!

그래픽 모드에서 상황은 비슷했습니다. 화면의 각 픽셀은 메모리의 특정 위치와 연결되어 있으며 BIOS 세트 픽셀 인터페이스가 있었지만 고성능 작업을하려면 메모리에 직접 기록해야합니다. VESA와 같은 최신 표준을 사용하면 시스템이 느린 BIOS 기반 쿼리를 수행하여 하드웨어의 메모리 레이아웃을 학습 한 다음 메모리로 직접 작업 할 수 있습니다. 최신 OS에는 모든 주요 GPU 제조업체의 하드웨어에 대한 기본 드라이버도 포함되어 있지만 OS에서 특수 드라이버없이 그래픽을 표시하는 방법입니다. 최신 NVidia 카드조차도 IBM CGA로 돌아가는 여러 가지 하위 호환성 모드를 지원합니다.

3D 그래픽과 2D의 중요한 차이점 중 하나는 2D에서는 일반적으로 매 프레임마다 전체 화면을 다시 그릴 필요가 없다는 것입니다. 3D에서 카메라가 조금이라도 움직이면 화면의 모든 픽셀이 변경 될 수 있습니다. 2D에서 스크롤하지 않으면 대부분의 화면이 프레임마다 변경되지 않으며 스크롤하더라도 화면 전체를 재구성하는 대신 일반적으로 빠른 메모리 간 복사를 수행 할 수 있습니다. 따라서 매 프레임마다 모든 픽셀에 대해 INT 10h를 실행하는 것과 같습니다.

출처 : 난 정말 늙었다


매우 유익합니다. 감사합니다. 하나 이상을 수락 할 수 있기를 바랍니다!
도디

8

부팅하는 동안 시스템 BIOS 는 비디오 어댑터를 찾습니다. 특히 비디오 어댑터의 내장 BIOS 프로그램을 찾아서 실행합니다. 이 BIOS는 일반적으로 메모리의 C000h 위치에 있습니다. 시스템 BIOS는 비디오 BIOS를 실행 하여 비디오 어댑터를 초기화합니다.

OS 또는 드라이버없이 BIOS가 기본적으로 표시 할 수있는 비디오 / 그래픽 레벨 또는 모드는 주로 비디오 BIOS 자체에 따라 다릅니다.

소스 / 추가 정보 - "시스템 부팅 순서"


6

우리 컴퓨터는 부팅 할 때 내가 아는 한 텍스트 모드에 있으며 AH = 0x0e 일 때 소프트웨어 인터럽트 0x10을 사용하여 문자를 표시 할 수 있습니다.

레거시 BIOS 기능에 대해 이야기하고 있습니다. 실제로 이러한 기능을 전혀 사용할 필요는 없습니다. 비디오 메모리에 직접 씁니다.

지구상에서 어떻게 컴퓨터가 OS보다 낮은 수준에서 그래픽을 출력합니까?

이것은 OS의 작동 방식과 밀접한 관련이 있습니다. 어쨌든 작업은 하드웨어 수준에서 동일합니다. 비디오 카드에는 비디오 RAM이있어 화면에 그릴 다음 이미지를 저장 (단순화)합니다. 각 주소는 픽셀을 나타내는 바이트라고 생각할 수 있습니다 (실제로는 일반적으로 픽셀 당 2 바이트 이상이 필요합니다). 그런 다음 비디오 컨트롤러는이를 모니터가 이해하는 신호로 변환합니다.

꼭짓점, 다각형, 글꼴 등의 기본 출력을 정의하는 표준이 있습니까 (예 : OpenGL에서 사용하는 OpenGL 아래)?

AFAIK, 아니요 논리적 그래픽 표현에 대한 표준은 없습니다.

공식 드라이버를 설치하지 않고 OS를 사용할 수있는 이유는 무엇입니까? 그들은 어떻게합니까?

OS와 함께 번들로 제공되는 드라이버가 있기 때문입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.