assembly BIOS读取字符宏在x86-16 MBR引导加载程序中仅工作一次

vc9ivgsu  于 2022-11-13  发布在  iOS
关注(0)|答案(1)|浏览(105)
org 0x7c00  
jmp _main

; _data:
playerPosition dw 0
; %1 == coluna (x)
; %2 == linha (y)
%macro drawRacket 2
    
    mov ah, 0ch ; print pixels mode
    mov dx, %2

    for1:
        mov bx, 32 ;racket height 
        add bx, %2
        cmp dx, bx  ; racket end (row)
        je .fim1
        mov cx, %1  ; racket beggining (column)
        jmp .for2
        jmp for1

        .fim1:
        jmp mainLoop

        ; loop to draw each line
        .for2:
        mov bx, 8 ;racket width
        add bx, %1
        cmp cx, bx   ;
        je .fim2
        mov al, 0x0f
        mov ah, 0ch
        int 10h
        inc cx
        jmp .for2

        .fim2:
        inc dx
        jmp for1

%endmacro

_main:
    ; 
    xor ax, ax
    mov ds, ax
    mov cx, ax
    mov dx, ax

    call setVideoMode

    ;racket initial position
    mov word[playerPosition], 10

    mainLoop:

        mov ah, 01h
        int 16h

        cmp al, 115
        je moveDown
        jmp mainLoop
    

jmp $

; 
setVideoMode: 
    mov ah, 0       ; 
    mov al, 13h     ;
    int 10h
ret

 moveDown:
     drawRacket 10, word[playerPosition]
     mov ax, word[playerPosition]
     inc ax
     mov word[playerPosition], ax
 jmp mainLoop

times 510-($-$$) db 0
dw 0xaa55

这是汇编代码。我试图使一个“乒乓球游戏”,我在非常beginning。我试图画第一个球员的球拍,但它是不工作。当我按“s”(mainLoop函数),它实际上工作并跳转到宏drawRacket并绘制它.但是,如果我再次按下“s”没有任何工作。。我已经尝试改变了很多东西的mainLoop功能,但没有任何工作,是什么让我认为我有一些问题的宏drawracet。我将感谢任何提示或答案。

frebpwbc

frebpwbc1#

但是,如果我再按“s”没有工作..
不管使用函数01 h而不是函数00 h的键盘问题如何,您的宏确实得到了第二次调用,并第二次绘制球拍,但它确实在绘制第一个球拍的位置进行了第二次绘制。这样,您看不到任何移动的东西!(要获得真正移动的感觉,您必须在绘制第二个球拍(部分)之前(部分地)移除第一个球拍)。
原因是宏的执行会以jmp mainLoop停止。这会略过递增 playerPosition 变数的程式码。快速的解决方法是将 .fim1 标签放在宏的底部附近。

%macro drawRacket 2
        mov     ah, 0Ch
        mov     dx, %2

        ...

    .fim2:
        inc     dx
        jmp     .for1

    .fim1:                            ; New position!
%endmacro

现在,宏代码将在递增Y的代码中失败。这是由于宏的工作方式。在程序中,drawRacket 10, word[playerPosition]行将被标记%macro drawRacket 2%endmacro之间的所有代码所替换。这个过程称为macro expansion
扩展后的版本如下所示:

moveDown:
        mov     ah, 0Ch              ; \
        mov     dx, [playerPosition] ;  \
                                     ;   \
        ...                          ;    \
                                     ;      The expanded macro code   
    drawRacket.fim2:                 ;    /
        inc     dx                   ;   /
        jmp     drawRacket.for1      ;  /
    drawRacket.fim1:                 ; /
        mov     ax, [playerPosition]
        inc     ax
        mov     [playerPosition], ax
        jmp     mainLoop

键盘函数01 h检查键是否可用,并报告结果。您会在AX中收到键的预览,并且键不会从keybuffer中删除。下次您的代码使用此键盘函数01 h时,即使您按下键盘上的另一个键,您仍然会收到同一个键的预览。
你的程序只需要等待一个键并根据它来操作,使用键盘函数00 h就可以做到这一点。

mov     ah, 00h   ; BIOS.GetKeyboardKey
int     16h       ; -> AL is ASCII, AH is scancode

相关问题