使用int 10h BIOS鼠标+键盘在2位数计算器程序中显示输入错误

时间:2017-10-19 06:39:56

标签: assembly x86-16 bios

我正在组装一个鼠标操作的2位数计算器。但是我在显示输入时遇到问题。程序显示当前输入正常,但是它输入它的列是错误的。以下是制作用户界面的完整代码:

mov ax, 06h ;ENTER GRAPHICS MODE
int 10h

mov ax, 1   ;SHOW MOUSE CURSOR
int 33h

mov cx, 20  ;INITIALIZE MOUSE CURSOR LEFT SIDE
mov dx, 20
mov ax, 4
int 33h

ui:
    mov dh, 1   ;TOP AND BOTTOM INITIAL ROW
    mov dl, 31  ;TOP AND BOTTOM INITIAL COLUMN
    mov al, '#'

    TopBottom:  ;TOP AND BOTTOM BORDER
        mov ah, 02h ;TOP    ;SET CURSOR POSITION
        int 10h
        mov ah, 0eh ;TELETYPE
        int 10h

        mov dh, 14
        mov ah, 02h ;BOTTOM
        int 10h
        mov ah, 0eh
        int 10h

        mov dh, 1
        inc dl
        cmp dl, 49
        jne TopBottom

    mov dh, 2   ;LEFT AND RIGHT INITIAL ROW
    mov dl, 31  ;LEFT AND RIGHT INITIAL COLUMN

    LeftRight:  ;LEFT AND RIGHT BORDER
        mov ah, 02h ;LEFT
        int 10h
        mov ah, 0eh ;TELETYPE
        int 10h

        mov dl, 48  
        mov ah, 02h ;RIGHT
        int 10h
        mov ah, 0eh ;TELETYPE
        int 10h

        mov dl, 31
        inc dh
        cmp dh, 14
        jne LeftRight

    mov dh, 4   ;MIDDLE INITIAL ROW
    mov dl, 32  ;MIDDLE INITIAL COLUMN

    Middle: ;MIDDLE LINE
        mov ah, 02h
        int 10h

        mov ah, 0eh
        int 10h

        inc dl
        cmp dl, 48
        jne Middle

    mov dh, 6   ;CONTENT INITIAL ROW
    mov dl, 34  ;CONTENT INITIAL COLUMN
    mov al, 55  ;7

Content:    ;NUMBERS, OPERATIONS, AND EVERYTHING IN BETWEEN!!! :D
    mov cx, 0

    Num:    ;1-9
        mov ah, 02h
        int 10h

        mov ah, 0eh
        int 10h

        add dl, 3
        inc al
        inc cx 
        cmp cx, 3
        jne num

    add dh, 2
    mov dl, 34
    sub al, 6
    cmp al, 46
    jne Content

    ;PRINTING ADDITION SYMBOL
    mov dh, 6
    mov dl, 44
    mov al, 43

    mov ah, 02h
    int 10h

    mov ah, 0eh
    int 10h

    ;PRINTING SUBTRACTION SYMBOL
    mov dh, 8
    mov al, 45

    mov ah, 02h
    int 10h

    mov ah, 0eh
    int 10h

    ;PRINTING MULTIPLICATION SYMBOL
    mov dh, 10
    mov al, 42

    mov ah, 02h
    int 10h

    mov ah, 0eh
    int 10h

    ;PRINTING DIVISION SYMBOL
    mov dh, 12
    mov al, 47

    mov ah, 02h
    int 10h

    mov ah, 0eh
    int 10h    

    ;PRINTING ZERO    
    mov dh, 12  ;ZERO ROW
    mov dl, 34  ;ZERO COLUMN
    mov al, 48

    mov ah, 02h
    int 10h

    mov ah, 0eh
    int 10h

    ;PRINTING C (RESTART)
    mov dl, 37
    mov al, 99

    mov ah, 02h
    int 10h

    mov ah, 0eh
    int 10h

    ;PRINTING EQUALS SYMBOL
    mov dl, 40
    mov al, 61

    mov ah, 02h
    int 10h

    mov ah, 0eh
    int 10h

以下代码是在屏幕上显示输入的代码,但计数器似乎不起作用。虽然我正在添加1,但它在第一个循环中添加了2并且之后没有添加任何内容。我是装配新手,所以我可能会丢失或误用一些寄存器。请帮忙

mov bl, 0   ;COUNTER
func:
    mov ax, 0003h
    int 33h

    cmp bx, 0
    je func

    mov ax, 0004h   ;SET THE MOUSE CURSOR
    int 33h

    add bl, 1

    ;COMPARE ROW
    cmp cx, 286
    jl col1

    cmp cx, 310
    jl col2

    ;cmp cx, 334
    jmp col3

    col1:
        cmp dx, 59
        jl seven

        cmp dx, 76
        jl four

        cmp dx, 92
        jl one

        cmp dx, 108
        jl zero

    seven:
        mov al, 55
        jmp input

    four:
        mov al, 52
        jmp input

    one:
        mov al, 49
        jmp input

    zero:
        mov al, 48
        jmp input

    col2:
        cmp dx, 59
        jl eight

        cmp dx, 76
        jl five

        cmp dx, 92
        jl two

        cmp dx, 108
        jl thing

    eight:
        mov al, 56
        jmp input

    five:
        mov al, 53
        jmp input

    two:
        mov al, 50
        jmp input

    thing:
        jmp ui

    col3:
        cmp cx, 334
        jg col4

        cmp dx, 59
        jl nine

        cmp dx, 76
        jl six

        cmp dx, 92
        jl three

        cmp dx, 108
        jl equals

    nine:
        mov al, 57
        jmp input

    six:
        mov al, 54
        jmp input

    three:
        mov al, 51
        jmp input

    equals:
        jmp exit

    col4:
        cmp dx, 59
        jl addition

        cmp dx, 76
        jl subtraction

        cmp dx, 92
        jl multiplication

        cmp dx, 108
        jl division

    addition:
        mov al, 43
        jmp input

    subtraction:
        mov al, 45  
        jmp input

    multiplication:
        mov al, 42
        jmp input

    division:
        mov al, 47
        jmp input

input:
    mov dl, 42  ;SET INITIAL COL OF INPUT
    mov dh, 2   ;SET INITIAL ROW OF INPUT
    add dl, bl
    mov ah, 02h
    int 10h
    mov ah, 0eh
    int 10h

jmp func

exit:  

int 20h

2 个答案:

答案 0 :(得分:2)

mov bl, 0   ;COUNTER
func:
    mov ax, 0003h
    int 33h
    cmp bx, 0
    je func
    mov ax, 0004h   ;SET THE MOUSE CURSOR
    int 33h
    add bl, 1

您希望在BL寄存器中保留一个计数器,但是您错过了获取鼠标位置的调用返回BX寄存器中的按钮状态的事实。这不可避免地会破坏你的计数器,因为BLBX的低8位!

您可以选择将此计数器放在另一个免费注册表中,例如BP

    xor bp, bp     ;COUNTER=0
func:
    mov ax, 0003h
    int 33h
    cmp bx, 0
    je  func
    mov ax, 0004h  ;SET THE MOUSE CURSOR
    int 33h
    inc bp         ;COUNTER+1

另请注意,您使用的大多数BIOS功能都希望您在BH寄存器中指定显示页面。 (你根本不这样做!)这是将计数器保存在BL / BX寄存器中不是一个好主意的另一个原因。

答案 1 :(得分:2)

mov bl, 0   ;COUNTER

此处bl = 0注释为用作计数器

func:
    mov ax, 0003h
    int 33h

bx = button state - 这会覆盖bl计数器,因为bx是从bl(低8位)和bh组合的16位寄存器8位)。

总的来说,我不喜欢那个代码墙...你应该考虑一些公式来计算这个功能,让代码更紧凑。类似的东西(只是猜测你的汇编程序,使用MASM / TASM / emu8086的语法,没有测试任何东西):

UI_PAD_X  EQU      262
UI_PAD_Y  EQU      44

    ; ds is expected to point to data segment already
    mov   di,OFFSET inputBuffer  ; where input will be written
      ; di will hold pointer for next input storage all the time
input_loop:
    cmp   di,100+OFFSET inputBuffer
    jae   exit     ; full input buffer
    mov   ax, 0003h
    int   33h  ; [x, y] = [cx, dx] (640x200), buttons = bx
    test  bx,bx
    jz    input_loop  ; no button clicked
  ; recalculate [x, y] coordinates into index-like values
  ; deducted coordinates from OP: [262, 44] -> [358, 108]
  ; single button is 24x16
    cmp   cx,UI_PAD_X+(4*24)
    jge   input_loop  ; click way too right (no button)
    sub   cx,UI_PAD_X
    jl    input_loop  ; click way too left (no button)
    cmp   dx,UI_PAD_Y+(4*16)
    jge   input_loop  ; click way too down (no button)
    sub   dx,UI_PAD_Y
    jl    input_loop  ; click way too up (no button)
    ; cx /= 24 (by subtraction, as result is 0..3 only = fast)
    mov   ax,-1
input_loop_dix_by_24:
    inc   ax
    sub   cx,24
    jae   input_loop_dix_by_24
    mov   cx,ax    ; cx = 0..3 (column of click)
    shr   dx,4     ; dx /= 16 = 0..3 (row of click)
    ; dx = row*4 + column -> general index of button clicked (0..15)
    shl   dx,2     ; dx *= 4
    add   dx,cx
    ; dx = 0..15 index of button
    cmp   dx, 13
    je    ui         ; "C" button clicked
    cmp   dx, 14
    je    exit       ; "=" button clicked
    mov   bx,OFFSET buttonLabels
    add   bx,dx
    mov   al,[bx]    ; fetch input character ASCII code
    ; store input into total buffer
    mov   [di],al
    inc   di
    ; output buffer
    mov   dx,(2*256)+42   ; start at [42, 2] position
    mov   bx,1            ; bh = page = 0 and bl=1
    mov   ah, 02h
    int   10h             ; set cursor position
    ; output all characters from inputBuffer (at least one in already)
    mov   si,OFFSET inputBuffer
    mov   ah, 0eh
input_loop_print_buffer:
    lodsb      ; al = [si++]
    int   10h  ; ah=0e, al=char, bh=0, bl=1
    cmp   si,di   ; until whole buffer is printed
    jb    input_loop_print_buffer
    jmp   input_loop  ; wait for next click

在数据段中,必须设置一些内存:

buttonLabels:
    db    '7', '8', '9', '+'
    db    '4', '5', '6', '-'
    db    '1', '2', '3', '*'
    db    '0', 'C', '=', '/'

inputBuffer:
    db    100 dup (0)
嗯,这比我希望的要长一点,但希望它足够简单,可以给你一些新的想法,如何以不同的方式解决问题。