为什么光标在真实硬件上不垂直移动,但在虚拟机上却垂直移动?

时间:2019-01-02 14:31:09

标签: assembly operating-system x86-16 bootloader osdev

我想使用操作系统中的键来实现光标移动。我尝试使用此代码来做到这一点:

mouse:
mov ah,0h
int 16h

    cmp al, 107
    je Down


    cmp al, 105
    je Up


    cmp al, 106
    je Left


    cmp al, 108
    je Right

    jmp mouse

    Right:
        add dl, 1
        call SetCursor
        jmp mouse
        ret

    Left:
      sub dl, 1
      call SetCursor
      jmp mouse
      ret

   Up:
     sub dh, 1
     call SetCursor
     jmp mouse
     ret

   Down:
      add dh, 1
      call SetCursor
      jmp mouse
      ret

   SetCursor:
       mov ah, 02h
       mov bh, 00
       int 10h
       ret

Bootloader(一小部分):

%include "stage2info.inc"

STAGE2_LOAD_SEG  equ STAGE2_ABS_ADDR>>4

.stage2_loaded:
    mov ax, STAGE2_RUN_SEG      
    mov ds, ax
    mov es, ax
    jmp STAGE2_RUN_SEG:STAGE2_RUN_OFS

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

为什么光标在真实硬件上不能垂直移动,而在虚拟机上却不能垂直移动? 我试图更改键,但没有任何改变。 为什么代码不能在真正的硬件上运行? 我的代码错了吗?

1 个答案:

答案 0 :(得分:4)

问题和评论:

  • 要检查箭头键,您需要查看AH中的scancodes,而不是AL中的ASCII字符。扫描码为0x50(向下),0x48(向上),0x4b(左侧)和0x4d(右侧)
  • 在进入鼠标循环之前,请勿初始化 DH DL 。进入循环之前,用Int 10h/AH=3h检索当前坐标
  • 您不会测试屏幕顶部,左侧,右侧和底部边缘的边界,因此,如果光标超出边界,可能会发生意外情况
  • ret之后,您有不必要的jmp mouse指令,这些指令永远无法到达。
  • 您可以使用 INC DEC 指令从寄存器中进行加法或减法,而不必使用 ADD SUB ,值为1。
  • 对于正在查看问题的人们,所使用的引导程序是我在此Stackoverflow Answer中放在一起的模板。

此代码应该有效:

%include "stage2info.inc"
ORG STAGE2_RUN_OFS

BITS 16

MAX_ROW equ 25                  ; 80x25 screen extents
MAX_COL equ 80

mouse:
    mov ah, 3                   ; Get cursor BIOS call
    mov bh, 0                   ; Page number is zero
    int 10h                     ; DH and DL will be set to current coordinates.

    mov ah,0h
    int 16h

    cmp ah, 0x50
    je Down

    cmp ah, 0x48
    je Up

    cmp ah, 0x4b
    je Left

    cmp ah, 0x4d
    je Right

    jmp mouse

    Right:
      inc dl
      cmp dl, MAX_COL           ; Test for right edge.
      jl right_bound_ok
      mov dl, MAX_COL-1
    right_bound_ok:
      call SetCursor
      jmp mouse

    Left:
      dec dl
      jge left_bound_ok         ; Test for left edge (<0?)

      mov dl, 0
    left_bound_ok:
      call SetCursor
      jmp mouse

    Up:
      dec dh
      jge up_bound_ok           ; Test for upper edge (<0?)

      mov dh, 0
    up_bound_ok:
      call SetCursor
      jmp mouse

    Down:
      inc dh
      cmp dh, MAX_ROW           ; Test for bottom edge
      jl down_bound_ok
      mov dh, MAX_ROW-1
    down_bound_ok:
      call SetCursor
      jmp mouse

    SetCursor:
      mov ah, 02h
      mov bh, 00
      int 10h
      ret