【问题标题】:How to display images in real mode?如何在实模式下显示图像?
【发布时间】:2016-09-14 19:14:30
【问题描述】:

我正在学习操作系统。我已经通过引导加载程序和内核。当我使用 XP 操作系统时,我突然想知道如何使用第二阶段引导加载程序在实模式下显示图像(比如 logo.jpg)。有可能这样做吗?

因为我以为开机时显示的 XP 标志是实模式。

那么,我该怎么做呢? 即:我的引导加载程序加载第二阶段,第二阶段应该加载图像文件并显示它。

我应该使用资源链接器还是什么?

语言:8086 汇编

谢谢

【问题讨论】:

  • 借助现代显示设备的 VESA VBE 3-bios,我们可以切换到具有 8,16 位或 24/32 位颜色的视频模式,可能具有 1920x1200x32(16:10 纵横比)的宽屏分辨率示例比率)。更多详细信息可以在 vesa.org 的公共和免费文档“vbe3.pdf”中找到(需要注册/登录)。只有 4 位和 16 色的旧视频模式不太容易使用,因为它的性能不高需要一个端口访问来设置每个像素。
  • 是的,但通常你不想对引导加载程序中的可用硬件等做出乐观的假设......这就是为什么即使是现代 Windows 也可以显示非 VESA 引导屏幕(并且默认情况下会显示)如果我没记错的话,直到 Windows Vista)。

标签: assembly linker operating-system kernel bootloader


【解决方案1】:

您可以使用中断 10h 与 BIOS 交互来控制显卡。

维基百科:https://en.wikipedia.org/wiki/INT_10H
教程《视频编程I》:http://fleder44.net/312/notes/18Graphics/index.html

这里是一个例子,取自this website (license):

这是一个使用写入模式 2 的 MODE 12h 视频图形示例,其中包含 4 个平面。 只需在 640x480x16 屏幕上绘制一条从 (0,0) 到 (479,479) 的彩色线。 ;这段代码是用 NBASM 汇编的

.model tiny
.code
.186

           org 100h

           mov  ax,0012h                ; set mode to 640x480x16
           int  10h

           mov  ax,0A000h
           mov  es,ax

           ; start line from (0,0) to (639,479)
           mov  word X,0001h            ; top most pixel (0,0)
           mov  word Y,0001h            ;
           mov  byte Color,00h          ; start with color 0
           mov  cx,480                  ; 480 pixels
DrawLine:  call putpixel                ; put the pixel
           inc  word X                  ; move down a row and inc col
           inc  word Y                  ;
           inc  byte Color              ; next color
           and  byte Color,0Fh          ; 00h - 0Fh only
           loop DrawLine                ; do it

           xor  ah,ah                   ; wait for key press
           int  16h

           mov  ax,0003                 ; return to screen 3 (text)
           int  10h

           .exit                        ; exit to DOS


; on entry X,Y = location and C = color (0-15)
putpixel   proc near uses ax bx cx dx

; byte offset = Y * (horz_res / 8) + int(X / 8)

           mov  ax,Y                    ; calculate offset
           mov  dx,80                   ;
           mul  dx                      ; ax = y * 80
           mov  bx,X                    ;
           mov  cl,bl                   ; save low byte for below
           shr  bx,03                   ; div by 8
           add  bx,ax                   ; bx = offset this group of 8 pixels

           mov  dx,03CEh                ; set to video hardware controller

           and  cl,07h                  ; Compute bit mask from X-coordinates
           xor  cl,07h                  ;  and put in ah
           mov  ah,01h                  ;
           shl  ah,cl                   ;
           mov  al,08h                  ; bit mask register
           out  dx,ax                   ;

           mov  ax,0205h                ; read mode 0, write mode 2
           out  dx,ax                   ;

           mov  al,es:[bx]              ; load to latch register
           mov  al,Color
           mov  es:[bx],al              ; write to register

           ret
putpixel   endp

X          dw 00h
Y          dw 00h
Color      db 00h

.end

【讨论】:

  • 实际上我可以在真实模式下显示图像(比如logo.jpg)吗?我不想绘制图形而是显示图像。
  • 同样的事情。不过,解码 JPG 会不必要地复杂。只需将其存储为位图甚至原始像素数据。然后去把所有的像素画到屏幕上。砰,你刚刚显示了一张图片。
  • 好的,但是我应该如何从位图文件中获取像素并绘制它?
  • 你在写内核,对吧?您是否已经构建了文件系统?否则根本就没有诸如“文件”之类的东西......如果你还没有办法从磁盘加载东西,你需要将像素作为数组包含在你的代码中。
猜你喜欢
  • 2018-04-24
  • 2011-11-28
  • 2018-03-05
  • 1970-01-01
  • 2016-03-15
  • 1970-01-01
  • 2021-02-18
  • 1970-01-01
相关资源
最近更新 更多