title: Virtual keyboard in TASM
body: <p>I know it's quite a long-shot but I'm stuck in the middle of a school assembly project and as I'm pretty new to programming, I'm having a hard time tracking down the problem(s) in my code.</p>
  
  <p>I'm trying to make an virtual (on-screen) keyboard. The values of the location of each button is found in 2 arrays, one for the X value of the center of the button, other for the Y.</p>
  
  <p>Example arrays keyboard's top row:</p>
  
  <pre><code>x_arr dw 13,37,61,85,109,133,157,181,205,229
  y_arr dw 113,113,113,113,113,113,113,113,113,113
  </code></pre>
  
  <p>The computer waits for a mouse click from the user and using an algorithm finds if or which button was pressed, then matches that button with an array of ascii values of each letter:</p>
  
  <pre><code>letter_arr db 81,87,68,82,84,89,85,73,79,80 ;QWERTYUIOP
  </code></pre>
  
  <p>My program doesn't seem to work. I'll add the full code and a picture of the keyboard itself.</p>
  
  <p>Sorry if anything was bit messy. Thanks in advance!</p>
  
  <p><a href="https://i.stack.imgur.com/Dnlq6.png" rel="nofollow noreferrer">image link</a></p>
  
  <pre><code>IDEAL
  MODEL small
  STACK 0f500h
  ;---------------
  MAX_BMP_WIDTH = 320
  MAX_BMP_HEIGHT = 200
  SMALL_BMP_HEIGHT = 40
  SMALL_BMP_WIDTH = 40
  
  DATASEG
  
      ;------Image related data------
      OneBmpLine db MAX_BMP_WIDTH dup (0)  ;One Color line read buffer
      ScreenLineMax db MAX_BMP_WIDTH dup (0)  ;One Color line read buffer
      FileHandle dw ?
      Header db 54 dup(0)
      Palette db 400h dup (0)
      SmallPicName db 'keyboar1.bmp',0
      BmpFileErrorMsg db 'Error At Opening Bmp File .', 0dh, 0ah,'$'
      ErrorFile db 0
      BB db "BB..",'$'     
      BmpLeft dw ?
      BmpTop dw ?
      BmpColSize dw ?
      BmpRowSize dw ?
      ;-----Program related data-----
      mouse_click dw ?
      letter_arr db 81,87,68,82,84,89,85,73,79,80         ;array containing ascii values of letters
      x_arr dw 13,37,61,85,109,133,157,181,205,229        ;array containing x value of center of buttons representing letters in letter_arr
      y_arr dw 113,113,113,113,113,113,113,113,113,113    ;array containing y value of center of buttons representing letters in letter_arr
      mouse_last_button dw 0  ;holds the value of last mouse button clicked
      mouse_button dw 1       ;holds the value of mouse button clicked
  
  CODESEG
  
  ;================PROCEDURES================
  ;-----------------
  proc OpenShowBmp near
      push cx
      push bx
      call OpenBmpFile
      cmp [ErrorFile],1
      je @@ExitProc
      call ReadBmpHeader
      ; from  here assume bx is global param with file handle. 
      call ReadBmpPalette
      call CopyBmpPalette
      call ShowBMP 
      call CloseBmpFile
  @@ExitProc:
      pop bx
      pop cx
      ret
  endp OpenShowBmp    
  ;-----------------
  proc OpenBmpFile    near                         
  ;input dx filename to open  
      mov ah, 3Dh
      xor al, al
      int 21h
      jc @@ErrorAtOpen
      mov [FileHandle], ax
      jmp @@ExitProc  
  @@ErrorAtOpen:
      mov [ErrorFile],1
  @@ExitProc: 
      ret
  endp OpenBmpFile
  
  proc CloseBmpFile near
      mov ah,3Eh
      mov bx, [FileHandle]
      int 21h
      ret
  endp CloseBmpFile
  ;-----------------
  proc ReadBmpHeader  near                    
  ; Read 54 bytes the Header  
      push cx
      push dx
  
      mov ah,3fh
      mov bx, [FileHandle]
      mov cx,54
      mov dx,offset Header
      int 21h
  
      pop dx
      pop cx
      ret
  endp ReadBmpHeader
  ;-----------------
  proc ReadBmpPalette near
  ; Read BMP file color palette, 256 colors * 4 bytes (400h)
  ; 4 bytes for each color BGR + null)            
      push cx
      push dx
  
      mov ah,3fh
      mov cx,400h
      mov dx,offset Palette
      int 21h
  
      pop dx
      pop cx
  
      ret
  endp ReadBmpPalette
  ;-----------------
  proc CopyBmpPalette near                    
  ; Will move out to screen memory the colors
  ; video ports are 3C8h for number of first color
  ; and 3C9h for all rest                                 
      push cx
      push dx
  
      mov si,offset Palette
      mov cx,256
      mov dx,3C8h
      mov al,0  ; black first                         
      out dx,al ;3C8h
      inc dx    ;3C9h
  CopyNextColor:
      mov al,[si+2]       ; Red               
      shr al,2            ; divide by 4 Max (cos max is 63 and we have here max 255 ) (loosing color resolution).             
      out dx,al                       
      mov al,[si+1]       ; Green.                
      shr al,2            
      out dx,al                           
      mov al,[si]         ; Blue.             
      shr al,2            
      out dx,al                           
      add si,4            ; Point to next color.  (4 bytes for each color BGR + null)             
  
      loop CopyNextColor
  
      pop dx
      pop cx
  
      ret
  endp CopyBmpPalette
  ;-----------------
  proc ShowBMP 
  ; BMP graphics are saved upside-down.
  ; Read the graphic line by line (BmpRowSize lines in VGA format),
  ; displaying the lines from bottom to top.
      push cx
  
      mov ax, 0A000h
      mov es, ax
  
      mov cx,[BmpRowSize]
  
      mov ax,[BmpColSize] ; row size must dived by 4 so if it less we must calculate the extra padding bytes
      xor dx,dx
      mov si,4
      div si
      mov bp,dx
  
      mov dx,[BmpLeft]
  
  @@NextLine:
      push cx
      push dx
  
      mov di,cx  ; Current Row at the small bmp (each time -1)
      add di,[BmpTop] ; add the Y on entire screen
  
      ; next 5 lines  di will be  = cx*320 + dx , point to the correct screen line
      mov cx,di
      shl cx,6
      shl di,8
      add di,cx
      add di,dx
  
      ; small Read one line
      mov ah,3fh
      mov cx,[BmpColSize]  
      add cx,bp  ; extra  bytes to each row must be divided by 4
      mov dx,offset ScreenLineMax
      int 21h
      ; Copy one line into video memory
      cld ; Clear direction flag, for movsb
      mov cx,[BmpColSize]  
      mov si,offset ScreenLineMax
      rep movsb ; Copy line to the screen
  
      pop dx
      pop cx
  
      loop @@NextLine
  
      pop cx
      ret
  endp ShowBMP
  ;-----------------
  proc setGraphic
      ;sets graphic mode
      mov ax, 13h
      int 10h
      ret
  endp setGraphic
  ;-----------------
  proc initMouse
      ;initializes mouse
      mov ax, 0
      int 33h ;resets mouse
  
      mov ax, 1
      int 33h ;shows pointer
      ret
  endp initMouse
  ;-----------------
  proc initImage
      ;imports keyboard bitmap
      mov [BmpLeft],0
      mov [BmpTop],0
      mov [BmpColSize], 320
      mov [BmpRowSize] ,200
      mov dx,offset SmallPicName
      call OpenShowBmp
      ret
  endp initImage
  ;-----------------
  proc getMouseClick
      mov ax, [mouse_button] ;stores te value of the last state of the mouse
      mov [mouse_last_button], ax
  
      mov ax, 03h
      int 33h ;gets mouse information
  
      mov [mouse_button], bx ;saves the click inforamtion
      shr cx, 1 ;halves the x position value since the interrupt returns double
      ret
  endp getMouseClick
  ;-----------------
  proc checkMouseButton
      mov ax, [mouse_button]      ;waits for the user to click left mouse button
      cmp ax, 1
      jne mouseLoop
  
      cmp ax, [mouse_last_button] ;if button pressed before is the same as the current one,
      jne mouseLoop               ;skip the letter printing
      jmp doLoop
      ret
  endp checkMouseButton
  ;-----------------
  proc checkX 
      mov ax,cx   ;saves the x value of the click for later
      pop cx  ;pops the current value of counter to cx
      push ax
      mov si, offset x_arr
      add si,cx
      mov ax, [si]    ;moves the value at x array at index number cx (counter) to ax
  
      ;add ax, 9  ;checks if the click was inside a button range on x axis (9 pixels left and right of the center)
      pop cx
      cmp cx, ax
      ja mouseLoop
  
      mov ax, [si]
      sub ax, 9
      cmp cx, ax
      jb mouseLoop
  endp checkX
  ;-----------------
  proc checkY
      mov si, offset y_arr
      add si,cx
      mov ax, [si]
  
      sub ax, 9   ;checks if the click was inside a button range on y axis (9 pixels above and below the center)
      cmp dx, ax
      jb mouseLoop
  
      mov ax, [si]
      add ax, 9
      cmp dx, ax
      ja writeLetter
      ret
  endp checkY
  ;-----------------
  proc printLetter
      mov si, offset letter_arr   ;prints the letter whose ascii value matches the x and y values found previously
      add si,cx
      mov dl, [si]
      mov ah, 2h
      int 21h
      ret
  endp printLetter
  ;-----------------
  ;================PROCEDURES================
  
  start:
      mov ax,@data
      mov ds,ax
  
      call setGraphic ;sets graphic mode
      call initMouse ;initializes mouse
      call initImage  ;displays keyboard image
  
      mov cx, 10 ;iterates over all of the buttons in the keyboard until one matches a clicks location
  mouseLoop:
      push cx
      call getMouseClick
      call checkMouseButton
      call checkX
      call checkY
      pop cx
      dec cx
      loop mouseLoop
  
  writeLetter:
      call printLetter
  
  doLoop: 
      mov cx,10 
      jmp mouseLoop
  
  exit:
      mov ax, 4c00h
      int 21h
  END start
  </code></pre>