首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >X86-16函数01 ->更改目标和/或显示页面

X86-16函数01 ->更改目标和/或显示页面
EN

Code Review用户
提问于 2018-02-06 11:56:31
回答 1查看 69关注 0票数 1

此代码将包含在X86-16将ASCIIZ字符串直接写入视频中,并依赖于该代码中的某些声明。当与该代码组合时,以下列方式声明@ 1000:0的字符串将;

代码语言:javascript
复制
AscTxt:  db  01, 84H                           ; View page 0 output to 4
         db  'This is an example', 01, 40H     ; View page 4 output to 0
         db  'This is replacing whatever is on top line of page 0'
         db  0, 01, 0FH, 0, 0   ; Waits for response then view page 0

举个例子,让我们从这个开始。

这是您在输入.COM文件名@命令提示符后会看到的下一步内容。

注意游标如何没有移动到EOS。那是故意的。然后,在按下除ESC以外的任何键后,我们将返回到第0页,并替换顶部行。

代码语言:javascript
复制
; =============================================================================================
;    Change display and/or destination page

;   ENTER:  00  -     7 = Set do not change current page being displayed
;                   6-4 = Display page. Ignored if equal to active or but 7 set
;                     3 = Set, do not change display page
;                   2-0 = Destination page. Ignored if already pointing there or bit 3 set.

;   LEAVE:   DI = New pointer when applicable
;            DX = volatile, all others unchanged.

;   FLAGS:  Undefined
; ---------------------------------------------------------------------------------------------

    F01:    cmp     al, 1
            jnz     F02
            lodsb                       ; Read only parameter for this function

    ; Real mode has a few limitations in addressing far data, so this just seems to be the
    ; most practical way of addressing data in BDA

            push    bx

    ; Test bit 7 to determine if display page should be changed. If so, then bits 6-4 are
    ; ignored.

            test    al, 10000000B       ; Is bit 7 on
            jnz     .cDest              ; if so we are not changing display page

            push    ax                  ; Still going to need low nibble
            shr     ax, 4               ; Shift page number into low nibble
            cmp     al, [fs:DispPg]     ; Check BDA if anything actually needs done
            jz      .cDest - 1          ; Already on that page

    ; The intent of procedurd e as a whole is to avoid BIOS as much as possible, but I
    ; did not want to implement code to manipulate controller.

            mov     ah, SAP
            int     VIDEO
            pop     ax                  ; Restore value in low nibble

   .cDest:  test    al, 1000B           ; Is bit 3 on
            jnz     .exit               ; if so we are not changing destination page            ; Return to instruction just before label .next

    ; Check if there is any need to do anything by determining if destination video segment
    ; is already being pointed too.

            and     al, 7
            mov     dx, es              ; Get current video segment
            mov     dl, al
            add     dl, 0B8H
            cmp     dh, dl              ; ZF will be set if same segments
            jz      .exit

    ; Set new segment and then determine offset based on that pages cursor position from
    ; x/y coordinates specified in BDA.

            shl     dx, 8
            mov     es, dx              ; Set new segment

    ; Caret position of new page or even one that has been written to before is assumed
    ; to be the starting point of next write.

            mov     bx, Cursors         ; Point to beginning of array of vectors
            shl     ax, 1
            add     bl, al
            mov     dx, [bx]                ; Points into arrary of vectors in BDA

            mov     di, dx              ; Just in case we are already at 0,0.
            or      dx, dx
            jz      .exit

    ; If position is top/left, not much point multiplying by zero

            mov     al, dh
            imul    ax, 80              ; 80 x 25 x 16 color assumed
            and     di, 0FFH
            add     di, ax
            shl     di, 1               ; ES:DI set to new page & offset

    ; Restore non-volatile

    .exit:  pop     bx
            ret

      F02:  ret
EN

回答 1

Code Review用户

发布于 2018-02-07 20:43:36

最初的评论是:不清楚输入的是什么(推断它是关于字节[ds:si]的),我宁愿使用“参数”或“输入”单词。不清楚描述是关于比特的。并不是所有的参数都会被描述(代码也使用ds:si地址来表示lodsb)。打字。修改后的寄存器也是不完整的(同样是si)。等等。

代码语言:javascript
复制
F01:    cmp     al, 1
        jnz     F02

为什么名字像F01?只是为了这篇评论,还是实际的标签?用一些描述性更强的东西。

为什么当al不等于1时函数结束?应该在描述中提到,al必须是1才能工作。

我会让push bx更接近它被修改的区域,这样就可以很容易地看到整个push/pop块所在的区域,并且跨越更少的分支点(这总是容易出错的,以便在某些分支中保持正确的堆栈)。实际上,您可以用push/pop bx包围很少的指令,根本没有任何分支。

代码语言:javascript
复制
        push    ax                  ; Still going to need low nibble
        shr     ax, 4               ; Shift page number into low nibble
        cmp     al, [fs:DispPg]     ; Check BDA if anything actually needs done
        jz      .cDest - 1          ; Already on that page

Bug:如果ah包含一些较低的位,那么显示页面的值就会出错。应该是shr al,4

为什么是.cDest-1?首先,为什么cDest不是英语,以及为什么-1,在x86强大的机器上,绝对没有理由保存符号名或符号数量上的字节。1988年的电话,他们想要你的习惯回来。

更多的打字..。你的编辑器里没有拼写检查吗?:-o (我用简单的kate源代码,Shift+Ctrl+O会打开/关闭拼写检查,所以它不会在指令上打扰我,但我可以不时地使用它来查看评论)。

代码语言:javascript
复制
        mov     ah, SAP
        int     VIDEO

这将不会编译,您应该提供工作源代码以供评审。通过在发帖前自己建立它,你就可以避免一些意外,比如你想要的更多的东西。此外,我也不知道什么是SAPVIDEO,因此无法对其进行审查并提出任何建议。除了停止使用晦涩的短符号名称之外,这些名字不能用通俗易懂的英语理解。

代码语言:javascript
复制
        mov     bx, Cursors         ; Point to beginning of array of vectors
        shl     ax, 1
        add     bl, al

如果以后只使用shl al, 1,那么只执行al操作。这在我看来是个bug,因为您在ah中有任何东西,然后我意识到您只使用al就可以避免这种情况。

实际上,如果Cursors数组跨越256 B边界,则add bl,al将产生错误的地址,这将失败。

但是你并没有说明你是如何定义Cursors的,也许你确信它是很好的对齐,并且总是符合256 B的“页面”。

尽管如此,还可以考虑使用完整的16b值来计算整个and ax,7 add ax,ax add bx,ax的更健壮版本。

整套光标代码有点可疑,我指的是基于di的X,y计算,你不是已经有这样的代码了吗?

你是在优化速度吗?你不能这么说吗?(可能不是,因为您仍然处于真实模式中)

而且,imul ax, 80同样有风险,因为您没有指定ah内容(将与我对and ax,7的上述修改一起工作)。

我可能会编写单独的子例程来根据di坐标计算[x, y],例如:

代码语言:javascript
复制
; input: dh:dl = y:x of cursor
; output: di = text mode offset for cursor position
    getDiForCursorPosition:
            push    dx
            movzx   di, dh          ; di = y
            imul    di, 80          ; di = 80 * y
            movzx   dx, dl          ; dx = x
            add     di, dx          ; di = 80 * y + x
            add     di, di          ; di = (80 * y + x) * 2
            pop     dx
            ret

并在任何地方使用它(在您检查它是否正常工作之后,我没有调试它:)。

票数 -1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/186911

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档