【问题标题】:How to create a text editor in Assembly language?如何用汇编语言创建文本编辑器?
【发布时间】:2015-06-10 23:32:50
【问题描述】:

到目前为止,我已经创建了一个程序来读取箭头键并在屏幕上移动光标。首先,用户必须输入 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

【问题讨论】:

  • 您的编辑过多地改变了您的问题,将其更改为另一个问题并使答案无效。这是不允许的。您应该在新帖子中提出更新后的问题。
  • 对不起……这将是我最后一次这样做。我发布了另一个问题,但很快就被拒绝了,我真的很想了解一些我没有教过的东西。
  • 将新问题附加到现有问题上也不起作用。很少有人会看到它,也没有人会费心回答它。编辑已关闭的问题,以便将其缩小到可以回答的范围内,您将获得更好的运气。我们不能教你编程,也不能为你编写编辑器。您的问题需要更具体,我们才能为您提供帮助。

标签: assembly text keyboard text-editor


【解决方案1】:

您的代码有一些重要错误:

  • DL 代表 X,DH 代表 Y。您没有在标签“moveLeft”、“moveRight”、“moveUp”和“moveDown”中正确使用它们。
  • Int 16h 更适合箭头等特殊键。
  • 您每次按键后都在清屏,所以光标每次都回到左上角。

这是您的代码经过改进,使用 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_linecurr_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),当用户按下键时,编辑器的第一行将消失,但是,当用户按下向上键时,可以从矩阵中重新显示第一行。

【讨论】:

  • 您能解释一下在 start 中与 ax 比较的值是什么(ASCII 值?)?对于任何其他特殊键,例如 shift、delete、page up 等... int 16h 也会有用吗?
  • 我明白了。所以对于所有其他特殊键,我也会这样做。另一个问题 - 为了能够将程序用作文本编辑器,我需要声明一个矩阵(但它是否只是 25 个大小为 80 的向量来填充整个屏幕?)。但是用户将如何决定该区域的“大小”?
  • 如果我使用 SI 作为指向字符串方向的指针,使用 DI 作为每个字符串的指针......我如何控制/访问特定字符串中的位置?例如,如果我有“mov SI, offset direc”然后是“mov di, row1”、“mov word ptr[si], di”、“add di, 2”,我如何访问 row1 的所有字节?我会创建一个变量以在 row1 内移动吗?
  • 从第一个“字符串”开始,是“mov curr_line, 1”,然后在写入/保存到字符串后,我会做“inc curr_line”还是“add curr_line, 80”就像你提到的移动上/下箭头键一样?
  • @user3053042,我用新代码编辑了我的答案:现在它显示字符,将这些字符存储在矩阵中,并相应地更新 curr_line 和 curr_char (如果你认为这个新代码值得投票,我赢了不要争论)。对了,我这里删掉了一些不必要的cmets。
【解决方案2】:

关于您的逻辑流程的一些要点。 moveRight:等四个函数,调整光标位置,跳转到prntCrs:这使得BIOS调用设置光标位置,然后运行到clearS:函数再跳转回start:

这些函数应该是called,并在末尾有一个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

此外,在dhdl 中,您并不总是以正确的方式处理行和列,并且您的光标位置变量定义不正确

posX db 1 dup(0) ; dh = posX -> controls row
posY db 1 dup(0) ; dl = posY -> controls column

这些可以是单个字节(也更正了用法)

posX db 0        ; dl = posX  <--- swapped register names
posY db 0        ; dh = posY

最后你增加和减少光标位置,但未能检查其边界。仅当 > 0 时减小,仅在

【讨论】:

    猜你喜欢
    • 2015-05-04
    • 1970-01-01
    • 1970-01-01
    • 2020-01-17
    • 1970-01-01
    • 1970-01-01
    • 2010-12-24
    • 1970-01-01
    • 2021-08-30
    相关资源
    最近更新 更多