3

So far, I have a created a program to read the arrow keys and move the cursor around the screen. First the user must enter a 0 to start, and will be able to move around while getch() != 27 (ESC). However, the cursor doesn't move at all.

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

------------------------------------------------------------------

Let's say I have this:

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

How would I save user input?

    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
user3053042
  • 99
  • 2
  • 16
  • Your edits changed your question too much, changing it into another question and invalidating the answers. That's not allowed here. You should ask your updated question in a new post. – Ross Ridge May 27 '15 at 03:20
  • I'm sorry...it'll be the last time I do this. I've posted another question that was immediately shot down, and I really wanna understand certain things that I wasn't taught. – user3053042 Jun 10 '15 at 02:40
  • Appending a new question to an existing question isn't going to work either. Few people will see it and no one is going to bother answering it. You'll have better luck editing your closed question in order to narrow it down to something that can be answered. We can't teach you to program, or write your editor for you. You problems need to be more specific before we can help you. – Ross Ridge Jun 10 '15 at 03:37

2 Answers2

2

Your code has some important errors:

  • DL is for X and DH is for Y. You don't use them properly in your labels "moveLeft", "moveRight", "moveUp" and "moveDown".
  • Int 16h is better for special keys like arrows.
  • You were clearing the screen after every key, so the cursor was going back to the upper left corner every time.

Here is your code improved, tested with EMU8086 (the arrows point to the changes) :

.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

Edit : now it displays chars, adds the chars to the matrix, and updates curr_line and curr_char. I used colors for fun. It's still necessary to prevent the cursor not to go beyond the limits, for example, do not exceed columns 0 and 80. Next is the new code:

.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

The matrix will be necessary in case you want to save to a file or load from a file. Also, the matrix will be useful in case of an editor with more lines than the screen size, for example, if matrix has 100 lines (matrix db 80*100), when the user presses down key, the first lines of the editor will disappear, but, when the user presses up key, the first lines can be re-displayed from the matrix.

  • Could you explain what the values being compared to ax in start are (ASCII values?) ? And for any other special key, such as shift, delete, page up, etc... int 16h would be useful as well? – user3053042 May 26 '15 at 04:05
  • I see. So for all the other special keys, I would do the same. Another question - in order to be able to use program as a text editor, I would need to declare a matrix (but would it just be 25 vectors of size 80 to fill the whole screen?). But how would the user decide the "size" of the area? – user3053042 May 27 '15 at 01:09
  • If I am using SI as a pointer to string directions, and DI as a pointer for each string... how can I control/access a position in a specific string? For example, if I have" mov SI, offset direc" then "mov di, row1","mov word ptr[si], di","add di, 2", how can I access all of row1's bytes ? Would I create a variable to move within row1? – user3053042 Jun 06 '15 at 19:26
  • To start at the first "string", would it be" mov curr_line, 1" and then after writing/saving onto the string, would I do "inc curr_line" or "add curr_line, 80" like you mentioned for moving the up/down arrow keys? – user3053042 Jun 10 '15 at 01:09
  • @user3053042, I edited my answer with new code : now it displays chars, store those chars in a matrix, and updates curr_line and curr_char accordingly (if you think this new code deserves an upvote, I won't argue it). By the way, I deleted some unnecessary comments here. – Jose Manuel Abarca Rodríguez Jun 10 '15 at 15:20
2

Some points about your logic flow. The four functions moveRight: etc, adjust the cursor position, jump to prntCrs: which makes the BIOS call to set the cursor postion, then runs through into the clearS: function before jumping back to start:

These functions should be called and have a ret instruction at the end.

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

Also you don't always handle row and column the right way round, in dh and dl and your cursor position variables are incorrectly defined

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

these can be a single byte (corrected the usage too)

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

Finally you increment and decrement the cursor position, but fail to check its bounds. Only decrease if > 0, only increase PosX if < 79, PosY if < 24.

Weather Vane
  • 33,872
  • 7
  • 36
  • 56