2

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

我目前正在开发一个简单的 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 的值......有谁知道如何解决这个问题?

4

1 回答 1

2

因为DL已经有一部分DX你不能同时DL用来装颜色和DX用来装银行号码了。Jester 已经注意到了这一点

由于Services.svga.draw_background例程中的另一个问题,您将颜色放入BL寄存器的努力也失败了。

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

此代码段无法正确恢复寄存器!pop's 需要与 's 的顺序相反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 ( ) 而不是 words ( )
来加快速度!ECXCX

于 2018-06-10T19:28:58.963 回答