我知道这是一个漫长的过程,但是我被困在一个学校组装项目的中间,而且由于我对编程还很陌生,所以我很难在我的问题中查找问题代码。
我正在尝试制作虚拟(屏幕上的)键盘。每个按钮的位置值有2个数组,一个为按钮中心的X值,另一个为Y。
示例数组键盘的第一行:
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
计算机等待用户的鼠标单击,然后使用算法查找是否按下了按钮或按下了哪个按钮,然后将该按钮与每个字母的ascii值数组进行匹配:
letter_arr db 81,87,68,82,84,89,85,73,79,80 ;QWERTYUIOP
我的程序似乎不起作用。我将添加完整的代码和键盘本身的图片。
对不起,如果有什么麻烦的话。预先感谢!
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
答案 0 :(得分:1)
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
这是您的主程序循环。因为它们是过程,所以人们期望 getMouseClick , checkMouseButton , checkX 和 checkY 返回{ {1}}。
只有 getMouseClick 像下降程序一样!
但是:
a。 checkMouseButton 跳回到 mouseLoop 和 doLoop 。
b。 checkX 跳回到 mouseLoop ,甚至认为它弹出call
,而实际上它正在弹出返回地址!
C。 checkY 跳回到 mouseLopp 和 writeLetter 。
这些回调均不会删除返回地址和将CX
压入堆栈。
您需要完全重新考虑这一点...
CX
您知道dec cx
loop mouseLoop
已经减少了loop
寄存器。为什么要另外使用CX
指令?