尽管键入相同的代码 3 次,我如何仅使用一次新行代码打印新行 3 次
include emu8086.inc
ORG 100h
PRINT 'ENTER THREE INITIALS: '
MOV AH,1
INT 21H
MOV BL,AL
INT 21H
MOV CL,AL
INT 21H
MOV BH,AL
MOV AH,2
MOV DL,10
INT 21H ;NEW LINE
MOV DL,13
INT 21H
MOV AH,2
MOV DL,BL
INT 21h
MOV AH,2
MOV DL,10
INT 21H ;NEW LINE
MOV DL,13
INT 21H
MOV DL,CL
INT 21h
MOV AH,2
MOV DL,10
INT 21H ;NEW LINE
MOV DL,13
INT 21H
MOV DL,BH
INT 21h
RET
END
您所要做的就是将您编写了 3 次的换行代码块放入您可以call
的子例程中。
PrintCRLF:
push ax
push dx
mov dl, 13 ;Carriage return
mov ah, 02h ;DOS.DisplayCharacter
int 21h
mov dl, 10 ;Linefeed
mov ah, 02h ;DOS.DisplayCharacter
int 21h
pop dx
pop ax
ret
现在,程序中显示结果的部分变为:
call PrintCRLF
mov dl, bl ;1st initial
mov ah, 02h ;DOS.DisplayCharacter
int 21h
call PrintCRLF
mov dl, cl ;2nd initial
mov ah, 02h ;DOS.DisplayCharacter
int 21h
call PrintCRLF
mov dl, bh ;3rd initial
mov ah, 02h ;DOS.DisplayCharacter
int 21h
不要觉得有必要尽可能多地删除mov ah, 02h
。将这些保留下来可以形成一个有据可查的程序,多年来,我已经看到BIOS/DOS实现确实破坏了AX
寄存器,即使API另有说明也是如此。
作为一个例子,为了表明你可以在不调用子例程的情况下编写它,下面是一个使用循环的版本,如本注释所示:
push ax ;3rd initial in AL
push cx ;2nd initial in CL
push bx ;1st initial in BL
mov cx, 3
Next:
mov dl, 13 ;Carriage return
mov ah, 02h ;DOS.DisplayCharacter
int 21h
mov dl, 10 ;Linefeed
mov ah, 02h ;DOS.DisplayCharacter
int 21h
pop dx ;Pops 1st, 2nd, and 3rd initial to DL
mov ah, 02h ;DOS.DisplayCharacter
int 21h
dec cx
jnz Again
首先创建一个可以从主代码调用的子例程/函数,例如在主代码放置以下内容之后:
PRINT_NEW_LINE:
MOV AH,2
MOV DL,10
INT 21H ;NEW LINE (that's really amazing comment... not)
MOV DL,13 ; and now I realized you do 10,13 output
INT 21H ; but correct DOS <EOL> is 13,10
RET ; time to fix all that in next version below...
现在我将使用一些丑陋的技巧来创建 2x 和 3x 变体,而不仅仅是简单地调用上面的子例程,而是让 CPU 通过其代码,在调试器中尝试它是如何工作的(以及堆栈中的返回地址做什么(,然后整个新的子例程代码将是:
PRINT_NEW_LINE_THRICE:
CALL PRINT_NEW_LINE ; do 1x EOL, and then fall into "twice" code
PRINT_NEW_LINE_TWICE:
CALL PRINT_NEW_LINE ; do 1x EOL, and then fall into it again
PRINT_NEW_LINE:
PUSH AX
PUSH DX ; store original ax, dx values
MOV AH,2
MOV DL,13
INT 21H ; output NL (new line)
MOV DL,10
INT 21H ; output CR (carriage return)
POP DX ; restore original ax, dx value
POP AX
RET
现在在你的主代码中,只需做:
CALL PRINT_NEW_LINE_THRICE
以获得 3 倍新行输出。
"三次"子例程的不那么令人困惑和棘手的变体当然是:
PRINT_NEW_LINE_THRICE:
CALL PRINT_NEW_LINE
CALL PRINT_NEW_LINE
CALL PRINT_NEW_LINE
RET