【问题标题】:x86 assembly VGA graphics with NASM glitch?带有 NASM 故障的 x86 汇编 VGA 图形?
【发布时间】:2018-11-16 17:40:50
【问题描述】:

如果这个问题看起来有点愚蠢,我提前道歉......

我目前正在开发一个简单的 16 位实模式操作系统,使用 x86 程序集 (NASM) 和 Ubuntu Mate Linux 16.04.3 LTS 作为我的开发平台和用于调试系统的 Virtualbox。到目前为止编写的引导加载程序和底层内核代码工作正常,但是我似乎遇到了我正在编写的图形代码的一些问题。我已经通过 INT10h 切换到 640x480x256 分辨率的 SVGA:

Services.screen_textmode.enter_svga:
    pusha

    mov ax, 4F02h
    mov bx, 101h
    int 10h

    popa
    ret

然后将控制权转移回内核,该内核将像素的颜色保存在 dl 寄存器中的下一个函数(我遇到问题的函数)并调用该函数:

mov dl, 2
call Services.svga.draw_background

现在我遇到的问题是,在运行以下代码时,每次切换视频内存库时,它似乎都会掩盖 dl 寄存器所保存的字节并且会改变每个库的颜色,或者整个屏幕是纯黑色的。代码如下:

Services.svga.draw_background:
    pusha

    xor cx, cx
    xor dx, dx
    mov word [svga_bank], dx

    mov ax, 0A000h
    mov es, ax

.start_bank:
    mov di, cx
    mov [es:di], dl

.finish_bank:
    inc cx
    mov di, cx
    mov [es:di], dl

    cmp cx, 65535
    je .switch_bank
    jmp .finish_bank

.switch_bank:
    xor cx, cx

    mov word dx, [svga_bank]
    inc dx
    mov word [svga_bank], dx

    push ax
    push bx

    mov ax, 4F05h
    xor bx, bx
    int 10h

    pop ax
    pop bx

    cmp dx, 5
    je .done
    jmp .start_bank

.done:
    popa
    ret

我为什么要在 Services.svga.draw_background 函数运行之前设置 dl 背后的想法是,操作系统最终将能够加载配置文件,这些配置文件将为应用程序和菜单设置配色方案,从而使系统更具可定制性。

我已经尝试了所有方法:我找到了不同的银行切换方式,直接在 .start_bank 中设置 dl 等。没有任何效果,经过详尽的研究后我找不到任何东西。显然,如果我在银行切换期间不存储 dx 的值,即使存在导致系统进入无限循环的指令“inc dx”,它也永远不会改变,并且当银行切换正常工作时,改变值的行为dx 的值也会以某种方式改变 dl ​​的值...有谁知道如何解决这个问题?

【问题讨论】:

  • “改变 dx 的值也会以某种方式改变 dl ​​的值”——你知道 dldx 的低 8 位,对吧?
  • 不,我没有。我再次道歉......如果你不能告诉我,我仍然是一个 asm 的菜鸟。冒着听起来更无聊的风险,似乎如果我从使用 dl 切换到 bl,我会在屏幕上看到相同的颜色,就在其他所有银行中(银行 0:我正在寻找的颜色,银行 2:黑色,银行 3:我的颜色等)。我将不得不进行更多测试,但感谢您向我指出这一点。
  • 可能重复(如果这个误解是您的主要错误):x86 Calculating AX given AH and AL? 显示 AX 分解为 AH:AL,对于 BX、CX、DX 也是如此。

标签: assembly x86 operating-system nasm vesa


【解决方案1】:

因为DL 已经是DX 的一部分,所以您不能同时使用DL 保存颜色并使用DX 保存银行编号。这是already noticed by Jester

您的努力 to put the color in the BL register instead 也因 Services.svga.draw_background 例程中的其他问题而失败。

push ax
push bx
mov ax, 4F05h
xor bx, bx
int 10h
pop ax
pop bx

这个 sn-p 没有正确恢复寄存器! pop 的顺序需要与 push 的顺序相反。

push ax
push bx
...
pop  bx
pop  ax

xor dx, dx
mov word [svga_bank], dx

在这个 svga_bank 变量中移动零并开始写入第一个银行是不够的。实体银行选择可以指向任何其他银行。例如在这个 Services.svga.draw_background 例程结束时,物理银行是 5,一个甚至无效的银行编号(这里的有效范围是 [0,4])!


为了您的方便,我写了这个。我已经把颜色放在CL

Services.svga.draw_background:
    pusha
    push ds
    mov  ax, 0A000h
    mov  ds, ax          ; DS:DI is start of video
    xor  di, di
    mov  ch, cl          ; CL holds the color [0,255]
    xor  dx, dx          ; Initial bank
  .again:
    mov  ax, 4F05h       ; VESA.SelectBank 0, 1, 2, 3
    xor  bx, bx
    int  10h
  .color:
    mov  [di], cx
    add  di, 2
    jnz  .color

    inc  dx
    cmp  dx, 4
    jb   .again

    mov  ax, 4F05h       ; VESA.SelectBank 4
    xor  bx, bx
    int  10h
  .LastBank:
    mov  [di], cx
    add  di, 2
    cmp  di, 45056
    jb   .LastBank

    pop  ds
    mov  word [svga_bank], dx
    popa
    ret

640 x 480 的分辨率提供 307200 字节。那是 65536 字节的 4 倍,剩下的 45056 字节。

提示
您可以通过编写 dwords (ECX) 而不是单词 (CX) 来加快速度!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-26
    • 2014-06-24
    相关资源
    最近更新 更多