在 DOSBox 中使用 TASM 运行汇编代码。我正在尝试在显示器中央打印我的名字。字母应按如下方式打印:第一个字母,然后应显示从第一个字母开始的每个字母以及当前字母,例如 name = carlton
首先打印c
然后 c 和 a
然后 c,a,r
然后 c、a、r、l 等
这是我尝试过的。我得到了一个无限循环,并且没有接近预期的结果。我认为我的方法还可以,但是编码有很多问题。
.MODEL SMALL
.STACK 64
.DATA
my_string db "Carlton", 0
count1 db 07
buffer db 07 dup(0)
count2 dw 0ffffh ;delay
.CODE
MAIN: mov ax,@DATA
mov ds,ax
; initialize pointer to point to my_string
mov bx, offset my_string
mov di, offset buffer
outer_loop: ; outer loop to iterate through each letter
;clearing the screen
MOV AX,0600H ;scroll the entire page
MOV BH,07 ;normal attribute
MOV CX,0000 ;row and column of the top left
MOV DX,184FH ;row and column of the bottom right
INT 10H ;invoke interrupt 10H
;setting the cursor to the center of the screen
MOV AH,02 ;set cursor option
MOV BH,00 ;page 0
MOV DL,39 ;center column position
MOV DH,12 ;center row position
INT 10H ;invoke interrupt 10H
; print current letter
mov di,[bx] ; store current character in di, wc pionts to buffer
mov ah,09
mov dx, di
int 21h
dec count2 ;decrement delay
jnz outer_loop
; inner loop to print buffer before current letter
print_prev:
cmp di,[bx]
je next
mov ah, 09
mov dx, di
int 21h
inc di
jmp print_prev
; increment pointer to next letter
next:
inc bx
dec count1
mov count2,0ffffh
jnz outer_loop
; exit program
mov ah,4ch
int 21h
END MAIN
甚至在尝试打印第一个字母之前,“清除屏幕”和“将光标设置到屏幕中心”就会破坏您的 BX 指针!请记住,BH(用于属性和显示页码)是 BX 寄存器的顶部。
您似乎认为DOS函数09h显示单个字符。事实并非如此:该函数显示以 $ 符号结尾的字符串(并且 $ 符号本身根本不显示)。对于单字符输出,请使用 DOS 功能 02h。
您的outer_loop可能很容易被称为无限循环,因为它会清除屏幕65535次并显示一些垃圾字符。
如果您的 print_prev 循环预计会打印单个字母,那么您对
inc di
有何期望,逻辑上会增加一个字符?
mov di,[bx] ; store current character in di
清楚地表明了对指针和方括号的误解。该特定指令从字符串中加载 2 个字符,同时破坏您在 DI 中设置的缓冲区指针。
不清楚你到底想输出到屏幕上的是什么, 但从你的提及来看:
首先打印 c 然后 c 和 a 然后 c,a,r 然后 c,a,r,l 等
我认为您可能正在寻找:
wait 1 sec
1st screen: c
wait 1 sec
2nd screen: ca
wait 1 sec
3rd screen: car
wait 1 sec
4th screen: carl
wait 1 sec
5th screen: carlt
wait 1 sec
6th screen: carlto
wait 1 sec
7th screen: carlton
下一个代码为例:
;clearing the screen
;setting the cursor to the center of the screen
; showing the name one character at a time
mov si, offset my_string
TheLoop:
; Wait 1 sec
mov ah, 2Ch ; DOS.GetSystemTime
int 21h ; -> CX DX
mov bl, dh ; Keep seconds
NotYet:
mov ah, 2Ch ; DOS.GetSystemTime
int 21h ; -> CX DX
cmp dh, bl ; Did seconds change ?
je NotYet
; Show next character, previous characters already in place
mov dl, [si]
mov ah, 02h ; DOS.DisplayCharacter
int 21h
inc si
dec count1
jnz TheLoop