我怎样才能在汇编中用循环打印字符对角线

How can i print characters diagonal with loop in assembly

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

但效果不佳。

顺便说一句,抱歉我的英语不好,这是我第一次 post 到 Whosebug。

前言

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

在您尝试编写一个在屏幕上产生对角线的循环时,您无法仅凭 incrementing/decrementing 光标的位置而逃脱,因为

  • 屏幕不是正方形的,这意味着 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

我意识到这个答案中可能有很多新内容。请花时间理解我编写的每一行代码。不要仅仅复制它就满足自己。如有疑问,请不要犹豫 post 对此答案发表评论!不客气。