此代码将包含在X86-16将ASCIIZ字符串直接写入视频中,并依赖于该代码中的某些声明。当与该代码组合时,以下列方式声明@ 1000:0的字符串将;
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页,并替换顶部行。

; =============================================================================================
; 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发布于 2018-02-07 20:43:36
最初的评论是:不清楚输入的是什么(推断它是关于字节[ds:si]的),我宁愿使用“参数”或“输入”单词。不清楚描述是关于比特的。并不是所有的参数都会被描述(代码也使用ds:si地址来表示lodsb)。打字。修改后的寄存器也是不完整的(同样是si)。等等。
F01: cmp al, 1
jnz F02为什么名字像F01?只是为了这篇评论,还是实际的标签?用一些描述性更强的东西。
为什么当al不等于1时函数结束?应该在描述中提到,al必须是1才能工作。
我会让push bx更接近它被修改的区域,这样就可以很容易地看到整个push/pop块所在的区域,并且跨越更少的分支点(这总是容易出错的,以便在某些分支中保持正确的堆栈)。实际上,您可以用push/pop bx包围很少的指令,根本没有任何分支。
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 pageBug:如果ah包含一些较低的位,那么显示页面的值就会出错。应该是shr al,4。
为什么是.cDest-1?首先,为什么cDest不是英语,以及为什么-1,在x86强大的机器上,绝对没有理由保存符号名或符号数量上的字节。1988年的电话,他们想要你的习惯回来。
更多的打字..。你的编辑器里没有拼写检查吗?:-o (我用简单的kate源代码,Shift+Ctrl+O会打开/关闭拼写检查,所以它不会在指令上打扰我,但我可以不时地使用它来查看评论)。
mov ah, SAP
int VIDEO这将不会编译,您应该提供工作源代码以供评审。通过在发帖前自己建立它,你就可以避免一些意外,比如你想要的更多的东西。此外,我也不知道什么是SAP或VIDEO,因此无法对其进行审查并提出任何建议。除了停止使用晦涩的短符号名称之外,这些名字不能用通俗易懂的英语理解。
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],例如:
; 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并在任何地方使用它(在您检查它是否正常工作之后,我没有调试它:)。
https://codereview.stackexchange.com/questions/186911
复制相似问题