到目前为止,我创建了一个程序来读取箭头键并在屏幕上移动光标。首先,用户必须输入0才能启动,并且能够在getch()!= 27(ESC)时移动。但是,光标根本不会移动。
model tiny
.code
org 100h
program:
mov cx, 10
mov ah, 7
int 21h
cmp al, 0 ; start
je clearS ; clear screen
start:
mov ah, 7 ; AL = getch()
int 21h
cmp al, 27 ; ESC
je fin
cmp al, 72
je moveUp
cmp al, 75
je moveLeft
cmp al, 77
je moveRight
cmp al, 80
je moveDown
moveRight:
mov dl, posY
inc dl ; posY ++
mov posY, dl
jmp prntCrs
jmp start
moveLeft:
mov dh, posX
mov dl, posY
dec dl ; posY --
mov posY, dh
jmp prntCrs
jmp start
moveUp:
mov dl, posY
mov dh, posX
dec dh ; posX --
mov posX, dh
jmp prntCrs ; print cursor
jmp start
moveDown:
mov dl, posY
mov dh, posX
inc dh ; posX ++
mov posX, dh
jmp prntCrs
jmp start
prntCrs: ; print cursor
mov ah, 2h
int 10h
clearS: ; clear screen
mov ah, 7
mov al, 25
mov ch, 0
mov cl, 0
mov dh, 24
mov dl, 79
int 10h
mov ah, 2
mov bh, 0
mov dh, 0
mov dl, 0
int 10h
jmp start
fin:int 20h
posX db 1 dup(0) ; dh = posX -> controls row
posY db 1 dup(0) ; dl = posY -> controls column
end program
我们说我有这个:
moveDown:
mov dl, posX
mov dh, posY
cmp dh, 9 ; limit
je stayLine
inc dh ; posY ++
mov posY, dh
add curr_line, 36 ;increment by line/string size
jmp prntCrs
goBackLine:
mov dl, posX
mov dh, posY
cmp dh, 1 ; limit
je stayLine
mov dl, 37
dec dh
mov posX, dl
mov posY, dh
sub curr_line, 36 ; go to start of last line
add curr_char, 35 ; to go to last char of last line
jmp prntCrs
nextLine:
mov dl, posX
mov dh, posY
mov dl, 1
inc dh
mov posX, dl
mov posY, dh
add curr_line, 36
mov curr_char, 0 ; or move it to whatever dl is?
jmp prntCrs
posX db 1 dup(1) ; dl = posX -> controls column
posY db 1 dup(1) ; dh = posY -> controls row
xlimit dw 38 ; number of columns (w/ border)
ylimit dw 10 ; number of rows (w/ border)
matrix db 36*8 dup(42)
curr_line dw ? ; pointer to current line
curr_char dw ? ; pointer to current char
如何保存用户输入?
mov si, offset ???
add si, curr_char
mov byte ptr [si], al
mov cl, dl ; to not lose value of posX
mov dl, al ; to be able to print
mov ah, 2h ; character output
int 21h ; display character in dl
mov dl, cl
inc dl ; to move right
mov posX, dl ; update posX
cmp posX, 38
je nextline
inc si
jmp writing
答案 0 :(得分:2)
关于你的逻辑流程的一些观点。四个函数moveRight:
等,调整光标位置,跳转到prntCrs:
,这使BIOS调用设置光标位置,然后运行到clearS:
函数,然后跳回{{ 1}}
这些函数应该start:
并且最后有call
条指令。
ret
此外,您始终无法在moveDown:
mov dl, posY
mov dh, posX
inc dh ; posX ++
mov posX, dh
call prntCrs ; call not jmp
jmp start
prntCrs: ; print cursor
mov ah, 2h
int 10h
ret ; added ret
和dh
中正确处理行和列,并且您的光标位置变量定义错误
dl
这些可以是单个字节(也纠正了用法)
posX db 1 dup(0) ; dh = posX -> controls row
posY db 1 dup(0) ; dl = posY -> controls column
最后,您增加和减少光标位置,但无法检查其边界。只有在>如果< 0,则仅增加PosX 79,PosY如果< 24。
答案 1 :(得分:1)
您的代码存在一些重要错误:
以下是您的代码改进,使用EMU8086进行测试(箭头指向更改):
.model tiny
.code
org 100h
program:
mov cx, 10
mov ah, 7
int 21h
cmp al, 0 ; start
je clearS ; clear screen
start:
mov ah, 0 ;<==================================
int 16h ;<==================================
cmp al, 27 ; ESC
je fin
cmp ax, 4800h ;<==================================
je moveUp
cmp ax, 4B00h ;<==================================
je moveLeft
cmp ax, 4D00H ;<==================================
je moveRight
cmp ax, 5000h ;<==================================
je moveDown
jmp start ;<==================================
moveRight:
mov dl, posX
mov dh, posY ;<==================================
inc dl ; posX ++
mov posX, dl
jmp prntCrs
jmp start
moveLeft:
mov dl, posX ;<==================================
mov dh, posY ;<==================================
dec dl ; posX -- ;<==================================
mov posX, dl ;<==================================
jmp prntCrs
jmp start
moveUp:
mov dl, posX ;<==================================
mov dh, posY ;<==================================
dec dh ; posY --
mov posY, dh ;<==================================
jmp prntCrs ; print cursor
jmp start
moveDown:
mov dl, posX ;<==================================
mov dh, posY ;<==================================
inc dh ; posY ++ ;<==================================
mov posY, dh ;<==================================
jmp prntCrs
jmp start
prntCrs: ; print cursor
mov ah, 2h
int 10h
clearS: ; clear screen
;mov ah, 7 ;<==================================
;mov al, 25 ;<==================================
;mov ch, 0 ;<==================================
;mov cl, 0 ;<==================================
;mov dh, 24 ;<==================================
;mov dl, 79 ;<==================================
;int 10h ;<==================================
;mov ah, 2 ;<==================================
;mov bh, 0 ;<==================================
;mov dh, 0 ;<==================================
;mov dl, 0 ;<==================================
;int 10h ;<==================================
jmp start
fin:int 20h
posX db 1 dup(0) ; dh = posX -> controls row
posY db 1 dup(0) ; dl = posY -> controls column
end program
编辑:现在它显示字符,将字符添加到矩阵,并更新curr_line
和curr_char
。我用颜色很有趣。仍然需要防止光标超出限制,例如,不要超过第0列和第80列。接下来是新代码:
.model tiny
.code
org 100h
program:
mov curr_line, offset matrix
mov curr_char, 0
start:
;CAPTURE KEY.
mov ah, 0
int 16h
;EVALUATE KEY.
cmp al, 27 ; ESC
je fin
cmp ax, 4800h ; UP.
je moveUp
cmp ax, 4B00h ; LEFT.
je moveLeft
cmp ax, 4D00H ; RIGHT.
je moveRight
cmp ax, 5000h ; DOWN.
je moveDown
cmp al, 32
jae any_char
jmp start
;DISPLAY LETTER, DIGIT OR ANY OTHER ACCEPTABLE CHAR.
any_char:
mov ah, 9
mov bh, 0
mov bl, color
mov cx, 1 ; how many times display char.
int 10h ; display char in al.
;UPDATE CHAR IN MATRIX.
mov si, curr_line ; si points to the beginning of the line.
add si, curr_char ; si points to the char in the line.
mov [ si ], al ; the char is in the matrix.
;!!! EXTREMELY IMPORTANT : PREVIOUS BLOCK DISPLAYS ONE
;CHAR, AND NEXT BLOCK MOVES CURSOR TO THE RIGHT. THAT'S
;THE NORMAL BEHAVIOR FOR ALL EDITORS. DO NOT MOVE THESE
;TWO BLOCKS, THEY MUST BE THIS WAY. IF IT'S NECESSARY
;TO MOVE THEM, ADD A JUMP FROM ONE BLOCK TO THE OTHER.
;RIGHT.
moveRight:
inc curr_char ; update current char.
mov dl, posX
mov dh, posY
inc dl ; posX ++
mov posX, dl
jmp prntCrs
;LEFT.
moveLeft:
dec curr_char ; update current char.
mov dl, posX
mov dh, posY
dec dl ; posX --
mov posX, dl
jmp prntCrs
;UP.
moveUp:
sub curr_line, 80 ; update current line.
mov dl, posX
mov dh, posY
dec dh ; posY --
mov posY, dh
jmp prntCrs ; print cursor
;DOWN.
moveDown:
add curr_line, 80 ; update current line.
mov dl, posX
mov dh, posY
inc dh ; posY ++
mov posY, dh
jmp prntCrs
prntCrs: ; print cursor
mov ah, 2h
int 10h
jmp start
fin:
int 20h
posX db 1 dup(0) ; dh = posX -> controls row
posY db 1 dup(0) ; dl = posY -> controls column
matrix db 80*25 dup(' ') ; 25 lines of 80 chars each.
curr_line dw ?
curr_char dw ?
color db 2*16+15
;FOR COLORS USE NEXT TABLE:
;http://stackoverflow.com/questions/29460318/how-to-print-colored-string-in-assembly-language/29478158#29478158
end program
如果要保存到文件或从文件加载,则必须使用矩阵。此外,如果编辑器的行数多于屏幕大小,矩阵将非常有用,例如,如果矩阵有100行(矩阵db 80 * 100),当用户按下键时,编辑器的第一行将是消失,但是,当用户按下键时,可以从矩阵中重新显示第一行。