Как нарисовать пиксель на экране без BIOS? - PullRequest
0 голосов
/ 20 декабря 2018

Я пишу ОС и хочу иметь графический интерфейс.Я не могу найти хороший учебник для рисования пикселей на экране.

Я хотел бы иметь пример сборки + C, который я могу построить и запустить на каком-нибудь эмуляторе, таком как BOCHS или v86

Ответы [ 2 ]

0 голосов
/ 04 апреля 2019

Верхний ответ очень хорошо объяснил.Вы просили какой-то пример кода, так что вот фрагмент кода из моего GitHub, и за ним последует подробное объяснение.

1. bios_setup:
2.  mov ah, 00h     ; tell the bios we'll be in graphics mode
3.  mov al, 13h
4.  int 10h         ; call the BIOS

5.  mov ah, 0Ch     ; set video mode
6.  mov bh, 0       ; set output vga
7.  mov al, 0       ; set initial color
8.  mov cx, 0       ; x = 0
9.  mov dx, 0       ; y = 0

10. int 10h         ; BIOS interrupt

В строке 2 начинается самое интересное.Во-первых, мы перемещаем значение 0 в регистр ах.В строке 3 мы перемещаем 13 шестнадцатеричных в al - теперь мы готовы к нашему вызову BIOS.Строка 4 вызывает bios с вектором прерывания 10 hex.BIOS теперь проверяет ах и ал.

AH:
 - tells BIOS to set video mode
AL:
 - tells BIOS to enter write string mode.

Теперь, когда мы вызвали прерывание в строке 4, мы готовы переместить новые значения в некоторые регистры.В строке 5 мы помещаем гекс 0C в регистр ах.Это говорит BIOS, что мы хотим написать графический пиксель.В строке 6 мы добавляем 0 в регистр bh, который сообщает BIOS, что мы будем использовать для вывода адаптер CGA, EGA, MCGA или VGA.Так что режим вывода 0 в принципе.И затем все, что нам нужно сделать, это установить наш цвет.Итак, давайте начнем с 0, который черный.Это все хорошо, но куда мы хотим нарисовать этот черный пиксель?Вот где появляются строки 8-9, где регистры cx и dx хранят координаты x, y пикселя для рисования соответственно.Как только они установлены, мы вызываем BIOS с прерыванием 10 hex.И нарисованный пиксель.

Прочитав подробный и информативный ответ Брендана, этот код будет иметь гораздо больше смысла.Определенные значения должны быть в определенных регистрах перед вызовом BIOS просто потому, что это регистры, в которых будет проверяться соответствующее прерывание.Все остальное довольно просто.Если вы хотите другой цвет, просто измените значение в al.Вы хотите моргнуть свой пиксель в другом месте?Возиться со значениями x и y в cx и dx.Опять же, это не очень эффективно для программ, интенсивно использующих графику, поскольку это довольно медленно.В образовательных целях, однако, это лучше, чем писать свой собственный графический драйвер;)

Вы все еще можете получить некоторую эффективность, рисуя все в буфере в оперативной памяти, прежде чем перейти к экрану, как сказал Брендан, но я бы оченьв моем примере это будет просто.

Посмотрите пример с полной бесплатностью на my GitHub .Я также включил README и Makefile, но они эксклюзивны для Linux.Если вы работаете в Windows, некоторое прибегание к поиску даст любую информацию, необходимую для сборки ОС на загрузочную дискету, и подойдет практически любой хост виртуальной машины.Кроме того, не стесняйтесь спрашивать меня обо всем, что неясно.Cheers!

Ps: я не писал инструмент, просто маленький скрипт в NASM, который предназначен для сборки на дискету и запуска в качестве ядра (в ВМ, если хотите)

0 голосов
/ 21 декабря 2018

Основная идея заключается в следующем:

1) загрузчик использует встроенное ПО (VBE для BIOS, GOP или UGA для UEFI) для установки графического режима, который поддерживается монитором, видеокартой и ОС;и при этом он получает соответствующую информацию (физический адрес буфера кадров, разрешение по горизонтали и вертикали, формат пикселей, байты между горизонтальными линиями) о буфере кадров из прошивки, которую он может передавать в ОС;так что ОС может использовать эту информацию во время «ранней инициализации» (до запуска собственного видеодрайвера) и может продолжать использовать ее (как своего рода «режим limp»), если нет подходящего родного видеодрайвера.

2) ОС использует информацию, чтобы выяснить, как записать в буфер кадра.Это может быть вычисление, подобное physical_address = base_address + y * bytes_between_lines + x * bytes_per_pixel (где bytes_per_pixel определяется из формата пикселей).

Примечания для "ранней инициализации":

  • по соображениям производительности, лучшечтобы нарисовать все в буфере в ОЗУ, а затем скопировать ("blit") данные из буфера в RAM в буфер кадров.
  • по соображениям производительности, код для копирования ("blit") данных избуфер в оперативной памяти в буфер кадров может / должен использовать некоторые приемы, чтобы избежать копирования данных, которые не изменились с прошлого раза
  • для поддержки множества различных форматов пикселей, можно использовать «стандартный» формат пикселей длябуфер в ОЗУ (например, может быть «8-битный красный, 8-битный зеленый, 8-битный синий, 8-битный отступ») и преобразовать его в любой пиксельный формат, который требуется видеокарте (например, возможно, «5-битный синий, 6-битный зеленый, 5-битный красный, без заполнения ») при копировании данных из буфера в ОЗУ в буфер кадра.Это позволяет вам иметь единую версию всех функций для рисования объектов (символы, линии, прямоугольники, значки, ...) вместо нескольких разных версий множества различных функций (по одной для каждого возможного формата пикселей).

Примечания для «средней инициализации»:

  • в конечном итоге ОС попытается найти и запустить подходящие драйверы устройств для всех различных устройств.Это включает в себя попытку найти подходящий драйвер для видеокарты (например, который поддерживает такие вещи, как вертикальная синхронизация, графический процессор, GPGPU и т. Д.).
  • вам потребуется разработать интерфейс видеодрайвера, который могут использовать нативные видеодрайверы.который (в идеале) поддерживает современные функции (например, полную 3D-графику и шейдеры).
  • , когда нет встроенного видеодрайвера, ОС может / должна запустить драйвер "универсального буфера кадров", который реализует тот же видеодрайверинтерфейс (который был разработан для поддержки аппаратного ускорения), который делает все в программном обеспечении без преимущества аппаратного ускорения.
  • при запуске видеодрайвера / ов операционная система должна иметь какую-то «передачу» в собственностьбуфера кадра передается из более раннего загрузочного кода в видеодрайвер.После этой «передачи» более ранний загрузочный код (который был разработан для рисования объектов непосредственно в буфере кадров) не должен касаться буфера кадров и должен попросить видеодрайвер выполнить работу «Преобразовать данные пикселей и скопировать в буфер кадров».

Примечания для "после инициализации":

  • Для традиционного "2D GUI";как правило, у вас есть один буфер (или «холст» или «текстура» или что-то еще) для фона / рабочего стола, плюс больше буферов / холстов для каждого окна или диалогового окна и, возможно, больше буферов / холстов для более мелких вещей (например, указатель мыши, падениевниз меню, «виджеты» и т. д.);таким образом, что приложения могут изменять свой буфер / холст (но по соображениям безопасности не имеют прямого или косвенного доступа к любому другому буферу / холсту).Затем графический интерфейс сообщает видеодрайверу, где должен быть нарисован каждый из этих буферов / холстов;и видеодрайвер (использующий аппаратное ускорение, если он является родным видеодрайвером) объединяет эти части вместе («компонует»), чтобы получить данные пикселей для всего кадра, затем выполняет преобразование формата пикселей (с надеждой, используя графический процессор), чтобы получить необработанные данные пикселей длядисплей / отправить на монитор.Это означает, что различные действия (перемещение окон по экрану, «альтернативные вкладки» между окнами, перемещение мыши и т. Д.) Становятся чрезвычайно быстрыми, когда есть встроенный видеодрайвер, потому что процессор ничего не делает, а сама видеокарта выполняет всю работу.

  • в идеале должен быть способ (например, OpenGL) для приложения попросить видеодрайвер нарисовать материал в буфере / холсте приложения;так что больше работы может быть сделано видеокартой (а не процессором).Это особенно важно для 3D-игр, но нет причин, по которым обычные 2D-приложения не могут использовать тот же подход для 2D-графики.

Обратите внимание, что большинство новичков делают все неправильно (неу него нет хорошо разработанного собственного интерфейса видеодрайвера) и, следовательно, никогда не будет иметь никаких собственных видеодрайверов, потому что все их программное обеспечение не может использовать собственный видеодрайвер в любом случае.Эти люди, вероятно, попытаются убедить вас, что это не стоит хлопот (поскольку, по их опыту, родные видеодрайверы никогда не будут существовать).Реальность такова, что большинство родных видеодрайверов крайне сложно написать, но некоторые из них (для виртуальных машин) не так сложно написать;и ваша цель должна состоять в том, чтобы в конечном итоге позволить другим людям писать драйверы (разрабатывая подходящие интерфейсы и предоставляя соответствующую документацию), а не писать все драйверы самостоятельно.

...