assembly 组件中的24比特图形模式

6uxekuva  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(745)

我想做一个操作系统(64位)。我做了一个编译器,输入,输出,我只需要有一个24位图形模式,使一个图形用户界面。我试图显示所有的颜色,但我只是得到这个混乱:

运行它代码:(仅在测试16位环境中)

[org 0x7c00]
  mov ax,4f02h
  mov bx,103h
  int 10h

        mov ax, 0a000h
mov es, ax
mov al, 0
 

mov edi, 0
mov eax, 0
sl:
stosw
inc edi
inc eax
jmp sl
times 510-($-$$) db 0
dw 0AA55h

我需要使它无中断,因为切换到64位模式时的cli指令。我希望我可以使它兼容任何分辨率,但我现在需要输出一个像素。我希望有人知道如何做到这一点,因为我没有发现任何东西是这个主题。
我试着把mov bx,103h切换到其他的东西,但是它只会让事情变得更糟。而且我甚至不能在64位模式下运行它,因为mov es,ax。

rks48beu

rks48beu1#

首先我强烈推荐阅读这篇文章:

像素渲染背后的思想是计算像素在VRAM中的地址,并复制该地址处的颜色或索引(使用VRAM所在的段,对于视频通常为A000h,对于文本模式通常为B800h)。

address = (x + y*x_resolution) * bytes_per_pixel

然而,通常我们只能访问VRAM的单个段,因此我们还需要选择它是哪一个(页),因此:

page = address / 65536
offs = address % 65536

现在你切换到页面(如果还没有),并复制像素颜色(1/2/4字节)在该地址,例如通过使用stosb/w/d。现在我不确定像素是否可以在2页一次(下面的代码不处理),所以如果真的,你也应该处理(但作为x分辨率的标准视频模式总是4的倍数,我不认为这是可能的)。
看起来你真的是一个新手,所以这里是一个小的简单(丑陋和slooooow)的例子(MS-DOS com可执行使用VESA BIOS在NASM)渲染像素在800 x600 x32位模式115 h...只是检查函数pixel,它期望800 x600 x32位视频模式和ax,bx作为x,y和ecx作为32位颜色:
第一个主要源文件:

[BITS 16]
[ORG 100h]

[SEGMENT .text]

start:  pusha
    mov ax,115h ; init 800x600 32bit
    call    vesamod

    mov al,0    ; set page to 0
    mov [cs:page],al
    call    vesapag

mainl0: mov ax,10
    mov bx,10
    mov ecx,003F7FFFh
l0: call    pixel
    inc ax
    inc bx
    cmp ax,110
    jnz l0

    mov ax,256  ; stop on any key hit
    int 16h
    jz  mainl0

    mov ax,3    ; return to 80x25 text mode
    int 10h
    popa
    ret

error:  mov ax,3
    int 10h
    popa
    popa
    ret

pixel:  pusha           ; ax=x, bx=y, ecx = color

    mov di,ax       ; eax = ( 800*y + x ) * 4
    mov eax,800
    and ebx,0FFFFh
    mul ebx
    mov bx,di
    add eax,ebx
    shl eax,2

    mov di,ax       ; di = eax % FFFFh (offset)
    mov ax,0A000h   ; es = A000h
    mov es,ax

    shr eax,16      ; ax = eax / FFFFh (page)
    cmp al,[cs:page]
    jz  .pixel0     ; change page if needed
    mov [cs:page],al
    call    vesapag

.pixel0:mov eax,ecx     ; eax = color
    stosd           ; render pixel
    popa
    ret

page:   db  0

%include 'vesa.lib'

和帮助器X1 M7 N1 X:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;VESA librrary ver: 1.0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;vesamod    set VESA videomode ax
;vesapag    al=page  switch vesa video page window A
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Vesa: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
vesamod:pusha               ;set VESA videomode ax
    mov     bx,ax
    mov     ax,4f02h
    int     16
    lea     si,[cs:.err]
    or      ah,ah
    jnz     near error
    popa
    ret
.err:   db  'VESA mode set error.',0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
vesapag:pusha               ;al=page  switch vesa video page window A
    mov     dl,al
    sub     dh,dh
    sub     bx,bx
    mov     ax,4f05h    ; window A
    int     16
    lea     si,[cs:.err]    ; error msg
    or      ah,ah
    jnz     near error
    popa
    ret
.err:   db  'VESA page switch error.',0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; End. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

请注意,我没有在asm编码的年龄,并没有国防部调整这在DOS框太多,所以它的丑陋和非优化。
这将使用函数pixel渲染蓝色对角线,这意味着颜色布局为:

ecx = 00RRGGBBh

有很多pusha/popa,我使用mul进行慢速计算,以提高性能。您应该有一个数组,用于存储每个扫描线的起始地址和页面,并预先计算一次(更改视频模式后),然后只需使用y访问它。此外,实际的page变量可以直接移动到vesapag函数中,但我没有心情编辑2个文件,因为我对MS真的很生疏-DOS和asm现在和DOS BOX是冲突的关键快捷方式与我的编辑器,更不用说VC编辑器停止工作,天知道是什么原因(花了我更多的时间来解决这个问题,比代码的例子本身)。
此外,如果你想使用32/64位代码,你将不得不使用某种扩展程序来访问VESA BIOS(或任何BIOS)功能或其替代品。从来没有做过这样的事情,但人们使用DOS 4GW为这早在一天...
此外,在32/64位模式下,您可以使用LFB(线性帧缓冲区),并完全忘记页面切换(提高速度很多)。
如果你想让这个工作的任何分辨率,那么你应该改变硬编码的800到真实的的分辨率你使用。它可以从VESA BIOS(沿着开始段)获得只是disect这个:

它获得所有可用的VESA视频模式沿着有关它们的信息,一旦你从列表中选择了一种,它就会呈现一个控制图像,这样你就可以看到8/15/16/32位模式之间的区别...

相关问题