首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >BIOS读取字符宏只在x86-16 MBR引导程序中工作一次。

BIOS读取字符宏只在x86-16 MBR引导程序中工作一次。
EN

Stack Overflow用户
提问于 2022-08-03 17:27:02
回答 1查看 68关注 0票数 0
代码语言:javascript
复制
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

这是装配代码。我正试着做一个“乒乓游戏”,而我却是在乞讨。我试着画出第一名球员的球拍,但这是行不通的。当我在键盘上按下"s“(mainLoop函数)时,它实际上工作并跳转到宏drawRacket并绘制它。但是,如果我再一次按下"s“,什么也不管用..。我已经尝试在mainLoop函数上更改了很多东西,但是没有什么效果,这使我认为宏drawRacket有一些问题。如有任何提示或回答,我将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-04 11:51:06

但是,如果我再一次按下"s“,什么也不管用..。

不管使用函数01h而不是函数00h的键盘问题,您的宏确实第二次调用并第二次绘制球拍,,但它这样做恰恰是在第一个球拍被画成的地方。你看不见有什么东西动了,那边!(对于真实运动的感觉,你必须先去除第一个球拍(部分),然后再画第二个球拍(部分))。

原因是宏的执行停止于一个jmp mainLoop。这绕过了增加playerPosition变量的代码。快速解决方案是将.fim1标签放置在宏的底部。

代码语言:javascript
复制
%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之间的所有代码。这个过程称为宏观展开

扩展的版本如下所示:

代码语言:javascript
复制
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

键盘功能01h检查是否有一个键可用,并报告事实。您将收到AX中的密钥预览,并且密钥不会从密钥缓冲区中删除。下一次当您的代码使用这个键盘函数01h时,即使您按下键盘上的另一个键,您仍然可以得到该键的预览。

你的程序只需要等待一个密钥并付诸行动。使用键盘函数00h,它可以做到这一点。

代码语言:javascript
复制
mov     ah, 00h   ; BIOS.GetKeyboardKey
int     16h       ; -> AL is ASCII, AH is scancode
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73225468

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档