assembly - 部件8086中的图形模式

标签 assembly graphics emu8086 vga

我有一个称为average的变量,在我的DATASEG中,它每次都会更改,因为用户每次都输入不同的输入。我想做的是进入图形模式(VGA),然后在此处打印您的平​​均值是:然后,平均值就知道如何更改为如下所示的图形模式:

mov ax, 13h  
int 10h

在打印平均值之后,如果平均值高于75 ,我想在下方打印。您是个好学生,请继续努力,如果不是。别担心,您会变得更好!
提前致谢。

最佳答案

我假设: PC VGA x86 MS DOS 平台

不管是真实的还是仿真的都没有关系,除非您想要低级的 IO 访问,而在 DOSBOX 等仿真中可能无法正常使用...

  • 视频/文本模式

    因此,要在视频和文本模式之间切换,您需要使用VGA BIOS:
    mov ax,mode ; here select which mode you want
    int 16      ; this calls EGA/VGA/VESA BIOS
    

    这里有许多video modes,这两个非常重要:
    mode | type  | segment | resolution         | align
    ----------------------------------------------------
    03   | text  | B800h   | 80x25 chars        | 2 Byte
    19   | video | A000h   | 320x200x256 colors | 1 Byte
    

    在视频模式19中,您可以通过访问段A000h处的内存来打印/查看像素,其中偏移量的计算方式如下:
    offset = 320*y + x
    
    320x200模式完全适合64 KByte段,因此您无需切换页面。这使其成为简单的asm gfx程序的理想选择。

    模式3是文本模式,其中每个字符的2 BYTEs一个是颜色,另一个是扩展的 ASCII 代码。再次通过访问段WORD处的B800h来完成打印/预览,其中偏移量为:
    offset = (80*y + x) * 2
    

    不确定两年前的两个字节是什么顺序,但是您可以轻松地测试在A上写入0B800:0000是否会在左上角呈现A或在0B800:0001中呈现。文本模式下的IIRC颜色仅是调色板中的前16种颜色,而颜色字节可编码墨水纸的亮度和闪光。此文本模式也是 MS-DOS shell正在使用的默认模式,因此您应在程序退出之前将其重新设置。

    因此,您的程序应如下所示:
    start:
        mov ax,19 ; set video mode
        int 16      
    
    mainloop:
        ; here your stuff
    
    exit:
        mov ax,3
        int 16
        ret
    
  • 打印字符串

    对于初学者,您可以将文本和视频模式结合起来……就像我在这里做的那样:
  • What is the best way to move an object on the screen?

  • 这是一个简单的游戏,菜单处于文本模式(打印很容易,只需将字符串复制到 VRAM 即可),而精灵图形游戏则处于320x200x256c视频模式。

    要以gfx模式打印时,首先需要在内存中添加一些字体。如果您查看 EGA / VGA BIOS 文档,则可以获取位于 EGA / VGA ROM中的字体,然后直接使用它。我还创建了此图像(使用Trident 9000 256 / 512KB VGA字体的IIRC),将其用作 OpenGL 和其他内容(无法访问 VGA BIOS 的等宽字体)的...

    在这里GLSL example of using it for printing您可以将其移植到 CPU / VGA / asm,但在 CPU 上的打印要简单得多,不需要像 GLSL 片段这样的可怕内容。

    因此,您只需要根据 ASCII 代码计算图像位置,并将其像素复制到 VRAM 中。在asm中粗略地拥有位图并不容易,更容易的是直接将其以二进制形式(作为db的集合),因此您可以编写一些简单的 C++ (或任何其他)脚本来加载图像并将其转换为asm源。 ..

    这是我几年前在 NASM 中写的一些古老的320x200x256 colors打印库(直接使用 EGA / VGA 字体):
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;GFX mode 13h print librrary ver:1.0
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;txti       init font adress
    ;char       cx=color,al=ASCII,scr:di<=al ;cl=ch => no background
    ;print      scr:di <= ds:si ,cx=color cl=ch => no background
    ;printl     scr:di text after call ,cx=color ...
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    txti:   pusha           ;init font adress
        push es
        mov ax,1130h    ; VGA BIOS - font info
        mov bh,3        ; font 8 x 8 pixels
        int 10h         ; ES:BP returns font address
        mov [cs:fonts],es   ;get font adr
        mov [cs:fonto],bp
        pop es
        popa
        ret
    fonts   dw 0        ; font address for printing ...
    fonto   dw 0
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    char:   pusha       ;cx=color,al=ASCII,scr:di<=al ;cl=ch => no background
        push    ds
        push    es
        push    word 0A000h
        pop es
        sub     ah,ah
        shl     ax,3
        mov     ds,[cs:fonts]
        mov     si,[cs:fonto]
        add     si,ax
        mov     dh,8
    .char0: mov     dl,8
        lodsb
        mov     ah,al
    .char1: mov     al,cl
        rcl     ah,1
        jc  .char2
        mov     al,ch
    .char2: cmp     cl,ch
        jz  .char3
        mov     [es:di],al
    .char3: inc     di
        dec     dl
        jnz     .char1
        add     di,320-8
        dec     dh
        jnz     .char0
        pop es
        pop     ds
        popa
        ret
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    print:  pusha       ;scr:di <= ds:si ,cx=color cl=ch => no background
    .l0:    lodsb
        or  al,al
        jz  .esc
        call    char
        add     di,8
        jmp     short .l0
    .esc:   popa
        ret
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    printl: mov [cs:.dat],si    ;scr:di text after call ,cx=color ...
        pop si
        push    ax
        push    di
        push    ds
        push    cs
        pop ds
    .l0:    lodsb
        or  al,al
        jz  .esc
        call    char
        add     di,8
        jmp     short .l0
    .esc:   pop ds
        pop di
        pop ax
        push    si
        add di,9*320
        mov si,[cs:.dat]
        ret
    .dat:   dw  0
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;; end. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    

    因此,要使用它,程序应类似于:
    start:
        call txti ; just once at program startup
    
        mov di,50+320*10
        mov cx,127
        call printl
        db  'SPEKTRA software & hardware',0
    
        mov di,50+320*30
        mov cx,127
        call printl
        db  'print test',0
    

    通过设置print来使用ds,si,以便它指向以null终止的字符串。正如您所看到的,printl不需要使用它,因为它使用直接位于printl调用之后的字符串,并且程序在它之后继续执行...这样,您就不需要指针设置指令或任何其他标签...颜色在cl,ch中是一种墨水,另一种是纸。如果是cl==ch,那么将不会仅渲染墨水像素,而如果您在文本后面放置图像或gfx背景,则墨水像素将不可用...颜色值可能不可见。我从我的一款游戏中获得了颜色,该游戏设置了自己的调色板因此,如果看不到任何内容,请尝试设置其他cl,ch(例如mov cx,0305h),看看这个:
  • standard VGA 256 color palette
  • Reading/Writing the VGA palette colors
  • 打印数字

    打印非负整数值是将数字除以基数(10)并以相反的顺序将remainder + '0'打印为字符的问题...

    hex中,甚至更容易,因为每个数字都对应于半字节<0-15>,因此对于16位,您可以通过xlat表或通过添加'0''A'来将最高4位转换为char,具体取决于值是否低于10……因此,没有除法位shift / mask ...打印字符并将值左移4位以处理下一位...

    gfx模式下的btw通常更好用和用户友好,而不是打印数值,因为数字可以像进度条一样显示进度条,而不是更容易...折叠成单循环渲染H或V线...就像REP STOSB :) ...
  • 关于assembly - 部件8086中的图形模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48648548/

    相关文章:

    android - 在 Android 上将 .so 代码从 ARM 转换为 x86

    java - 动态图形对象绘画

    c# - 围绕枢轴点重复旋转点

    assembly - 8086随机数生成器(不仅仅是使用系统时间)?

    linux - 基本 assembly 计算器分配不起作用

    c++ - "lock add"在x86处理器上是如何实现的

    string - assembly GDB 打印字符串

    c++ - Win32下如何初始化Pango?

    assembly - 如何使用emu8086读取硬件输入

    assembly - EMU8086显示屏(黑屏)