1

I am writing a bootsector game which attempts to copy the chrome dinosaur game you can play when you have no internet.

To do this, I must run from left to right until the player hits a cactus.

How do I achieve this? (How do I make the terminal scroll from right to left so that it looks like I am moving?) So instead of scrolling up and down, I need to scroll from right to left and left to right. I am in 16 bit real mode (BIOS), and I am using nasm / intel syntax.

4

1 回答 1

5

在与 CGA 兼容的文本模式中,屏幕内容存储在一个 4000 字节的缓冲区中B800:000(除非您更改活动显示页面,但我假设您不更改)。每行包含 80 个字符,存储在 160 个字节中,共 25 行,分辨率为 80×25。

因此,要向左滚动屏幕,您必须将屏幕的字符向左移动所需的列数,并用空白字符填充屏幕的右侧。这可以很容易地实现,使用一系列rep movsw指令来移动字符,然后使用rep stosw指令填充右侧。假设ds = es = b800并假设ds:di指向行首,将单行左移c列的代码如下所示:

        lea     si, [di+2*c]   ; set up SI to the column that is scrolled
                               ; into the first column of the line
        mov     cx, 80-c       ; copy all columns beginning at that column
                               ; to the end of the row
        rep     movsw          ; scroll row to the left
        mov     cx, c          ; need to blank that many columns
        rep     stosw          ; blank remaining columns

在此代码序列之后,DI指向下一行的开头。因此,通过将这个序列迭代 25 次,我们可以轻松地滚动整个屏幕:

        mov     ax, 0xb800     ; screen segment
        mov     ds, ax         ; set up segments
        mov     es, ax
        xor     di, di         ; point to the beginning of the screen
        mov     dx, 25         ; process 25 lines
        mov     ax, 0x0700     ; what to scroll in (grey on black blanks)

.loop:  lea     si, [di+2*c]   ; set up SI to the column that is scrolled
                               ; into the first column of the line
        mov     cx, 80-c       ; copy all columns beginning at that column
                               ; to the end of the row
        rep     movsw          ; scroll row to the left
        mov     cx, c          ; need to blank that many columns
        rep     stosw          ; blank remaining columns

        dec     dx             ; decrement loop counter
        jnz     .loop          ; loop until we're done

这就是它的全部。当然,如果c是变量而不是常量,代码会变得稍微复杂一些。但我相信你会弄清楚的。

另请注意,您似乎将屏幕称为“BIOS 终端”或类似名称。这是不正确的。屏幕由显卡绘制,实际上可以在没有 BIOS 的情况下完全更改。BIOS 是计算机上的 ROM 中提供的一组例程。其中包括一些用于配置图形模式和打印字符等的例程。但是,这纯粹是为了方便。您实际上不需要通过 BIOS 来执行任何这些操作。

于 2020-09-23T23:14:00.000 回答