如何在装配中用循环打印字符

时间:2017-05-30 11:26:31

标签: loops assembly x86-16 dosbox

CODE SEGMENT
ASSUME CS:CODE
START:  

MOV AH,06h ;INT 10,6
MOV AL,00h ;number of lines to scroll, previous lines are
;blanked, if 0 or AL > screen size, window is blanked
MOV CH,00h ;row of upper left corner of scroll window
MOV CL,00h ;column of upper left corner of scroll window
MOV DH,24h ;row of lower right corner of scroll window
MOV DL,79h ;column of lower right corner of scroll window
MOV BH,07h ;attribute to be used on blank line
INT 10h



MOV AH,02H
MOV BH,00H
MOV DH,01H
MOV DL,03H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,02H
MOV DL,06H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,03H
MOV DL,0AH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,04H
MOV DL,0DH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,05H
MOV DL,10H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,06H
MOV DL,14H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,07H
MOV DL,17H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,08H
MOV DL,1AH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,09H
MOV DL,1EH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,0AH
MOV DL,21H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,0BH
MOV DL,24H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,0CH
MOV DL,28H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,0DH
MOV DL,2BH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,0EH
MOV DL,2EH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,0FH
MOV DL,32H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,10H
MOV DL,35H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,11H
MOV DL,38H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,12H
MOV DL,3CH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,13H
MOV DL,3FH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,14H
MOV DL,42H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,15H
MOV DL,46H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,16H
MOV DL,49H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,17H
MOV DL,4CH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,18H
MOV DL,50H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h


;-------------------------------------------------------




MOV AH,02H
MOV BH,00H
MOV DH,01H
MOV DL,4DH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,02H
MOV DL,4AH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,03H
MOV DL,46H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,04H
MOV DL,43H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,05H
MOV DL,40H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,06H
MOV DL,3CH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,07H
MOV DL,39H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,08H
MOV DL,36H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,09H
MOV DL,32H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,0AH
MOV DL,2FH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,0BH
MOV DL,2CH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h



MOV AH,02H
MOV BH,00H
MOV DH,0DH
MOV DL,25H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,0EH
MOV DL,22H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,0FH
MOV DL,1EH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,10H
MOV DL,1BH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,11H
MOV DL,18H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,12H
MOV DL,14H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,13H
MOV DL,11H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,14H
MOV DL,0EH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,15H
MOV DL,0AH
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,16H
MOV DL,07H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,17H
MOV DL,04H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

MOV AH,02H
MOV BH,00H
MOV DH,18H
MOV DL,01H
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h





int 20h
CODE ENDS
END START

这是我想做的手动方式:)。我想增加或减少光标的行,循环内的列号,我试过这段代码

CODE SEGMENT
ASSUME CS:CODE
START:  

MOV CX,12
MOV DH,00H
MOV DL,00H

dongu:
MOV AH,02H
MOV BH,00H
MOV AH,02h
MOV DL,2Ah
inc dl
inc dh
INT 10H
loop dongu

INT 21h
int 20h
CODE ENDS
END START

但它运作不佳。

顺便说一句,抱歉我的英语不好,这是我第一篇关于stackoverflow的帖子。

1 个答案:

答案 0 :(得分:1)

序言

MOV AH,06h ;INT 10,6
MOV AL,00h ;number of lines to scroll, previous lines are
;blanked, if 0 or AL > screen size, window is blanked
MOV CH,00h ;row of upper left corner of scroll window
MOV CL,00h ;column of upper left corner of scroll window
MOV DH,24h ;row of lower right corner of scroll window
MOV DL,79h ;column of lower right corner of scroll window
MOV BH,07h ;attribute to be used on blank line
INT 10h

以上代码段已显示错误。您对十进制和十六进制数字感到困惑。右下角的坐标为(79,24)。你写了更大的值(79h,24h)=(119,36)。如果你很幸运,BIOS不会介意太多,但你不能指望这种宽大。

MOV AH,02H
MOV BH,00H
MOV DH,18H
MOV DL,50H     <<<<< This is off-screen!
INT 10H
MOV AH,02h
MOV DL,2Ah
INT 21h

第一对角线的最后一点是屏幕外。在接下来的解决方案中,我将纠正这一点。

inc dl
inc dh

在你尝试编写一个在屏幕上产生对角线的循环时,你不会因为增加/减少光标的位置而逃脱,因为

  • 屏幕不是正方形,表示DLDH不会同时改变。
  • 水平尺寸远大于垂直尺寸,意味着水平步长为3或4,垂直步长可以保持为1。

解决方案

对于一个简单的解决方案,它将产生与手动版本完全相同的输出,您可以存储在数组中使用的坐标,然后循环遍历此数据。因为该行确实可以使用递增1,所以不需要存储垂直分量。由于第二对角线与第一对角线对称,因此无需为第二对角线(*)存储单独的数据。
下一个代码将给出从(3,1)到(79,24)

的第一个对角线
array   db 3,6,10,13,16,20, ... ,73,76,79,-1
    ...
    mov     cx, 1        ;Repetition count for BIOS function 09h
    mov     bx, 0007h    ;BH=Display page 0, BL=Attribute WhiteOnBlack
    mov     si, array
    mov     dh, 0        ;Row
again:
    inc     dh           ;Vertical step is fixed at 1
    mov     dl, [si]     ;Column
    mov     ah, 02h      ;SetCursor
    int     10h
    mov     ax, 092Ah    ;AH=BIOS function 09h, AL=Character "*"
    int     10h
    inc     si
    cmp     byte ptr [si], -1  ;Reached end of list marker?
    jne     again

请注意我没有使用DOS功能02h输出字符。由于此DOS输出功能会自动前进光标,因此会在某些时候干扰您的屏幕。我使用的BIOS输出功能不会使光标前进,因此非常适合您的程序。

仔细观察(*)

array1  db 3,6,10,13,16,20, ... ,73,76,79,-1
array2  db 77,74,70,67,64,60, ... ,7,4,1,-1

如果你仔细观察第二对角线的数字,你会发现第一对角线的数字有相似之处。实际上,该列现在与屏幕的宽度互补:

77 = 80 -  3
74 = 80 -  6
70 = 80 - 10
...
 4 = 80 - 76
 1 = 80 - 79

现在我们可以利用它来编写第二个对角线的循环,只需对代码进行微小的更改:

array   db 3,6,10,13,16,20, ... ,73,76,79,-1
    ...
    mov     cx, 1        ;Repetition count for BIOS function 09h
    mov     bx, 0007h    ;BH=Display page 0, BL=Attribute WhiteOnBlack
    mov     si, array
    mov     dh, 0        ;Row
again:
    inc     dh           ;Vertical step is fixed at 1
    mov     dl, 80                              <<<<< Only changes
    sub     dl, [si]     ;Column                <<<<< Only changes
    mov     ah, 02h      ;SetCursor
    int     10h
    mov     ax, 092Ah    ;AH=BIOS function 09h, AL=Character "*"
    int     10h
    inc     si
    cmp     byte ptr [si], -1  ;Reached end of list marker?
    jne     again

我意识到这个答案中可能有很多新东西。请花时间了解我编写的代码的每一行。不要只是复制它来满足自己。如有疑问,请随时发表有关此答案的评论!不客气。