组装鼠标 w/o int33h

Assembly Mouse w/o int33h

好的,所以我从事汇编工作的时间足够长,足以理解体面的代码。

一直想把鼠标弄起来w/o int 33h 主要是因为VMware或者Bochs(模拟器w/o MS-DOS)中没有33h。

我的代码看起来正确吗?我关注了 OSDev Wiki 和 Cosmos c#

;====================================
;#Handles the mouse routines        #
;                                   #
;#TODO: Find a way to make it so    #
;#  the mouse_wait_signal times out #
;====================================

mouse_initalize:
    ;first enable IRQ12
    mov al, 0xA8        
    out 0x64, al        

    ;wait for signal
    call mouse_wait_signal

    ;next enable interrupt
    mov al, 0x20    ;command
    out 0x64, al

    ;wait for data
    call mouse_wait_data

    ;get data
    in al, 0x60
    mov [mouse_status], al

    ;wait for more signal
    call mouse_wait_signal

    ;command
    mov al, 0x60
    out 0x64, al

    ;wait le sig
    call mouse_wait_signal

    ;set the status
    in al, 0x60
    mov [mouse_status], al

    ;finnaly enable mouse

    ;---DEFAULT-----
    mov al, 0xF6
    call mouse_write
    call mouse_read ;acknowlage
    ;---DEFAULT-----

    ;---ENABLE------
    mov al, 0xF4
    call mouse_write
    call mouse_read ;acknowlage
    ;---ENABLE------

    ret

;------------------------------------
;Waits for signal from mouse port
mouse_wait_signal:
    ;save prev al
    mov [.buffer], al

.a1:;jump into this loop until we rec a signal
    in al, 0x64 
    cmp al, 0
    je .a1

    ;loop stoped meaning we have a signal
    mov al, [.buffer]
    ret

.buffer db 0x00

;------------------------------------
;Waits for data signal from port 0x64
mouse_wait_data:
    ;save prev al
    mov [.buffer], al

.a1:;jump into this loop until we rec a signal
    in al, 0x64 
    cmp al, 1
    jne .a1

    ;loop stoped meaning we have a signal
    mov al, [.buffer]
    ret

.buffer db 0x00

;------------------------------------
;Writes to the mouse
;IN: AL = cmd
mouse_write:
    ;save prev al
    mov [.buffer], al

    ;wait,send1,wait,sendcmd
    call mouse_wait_signal
    mov al, 0xD4
    out 0x64, al
    call mouse_wait_signal
    mov al, [.buffer]
    out 0x60, al

    ;loop stoped meaning we have a signal
    mov al, [.buffer]
    ret

.buffer db 0x00

;------------------------------------
;Reads the mouse
;RET: AL = data
mouse_write:
    call mouse_wait_data
    in al, 0x60
    ret

;===VARIABLES========================
mouse_status    db  0x00

从问题中不清楚,你的问题是什么,如果你要求完整的代码审查 + 调试,那是 AFAIK 而不是 "good" SO 问题,至少没有给出一些提示有多少问题以及可能存在哪些问题。

我还是花了大概15分钟快速看完,感觉质量不行先试一下,所以我不打算深究了,我就总结一下我不喜欢的地方远(如果我要进行全面审查,可能会有更多内容,但这将花费比我愿意投入的时间更多的时间)。免责声明:我从来没有为 PC 编写过自己的鼠标处理程序,所以我只是将您的代码与 OSDev Wiki 中的规范进行比较,如果这些有误,我的建议也会有误。


I followed OSDev Wiki

还有这个:

Since both keyboard and mouse data is showing up to be read on port 0x60, it is necessary to be able to tell which is which. To tell if there is any available data on port 0x60 at all, it is necessary to read a byte from port 0x64. In that byte from port 0x64, bit number 0 (value=1) indicates that a byte is available to be read on port 0x60. An additional bit, bit number 5 (value=0x20), indicates that this next byte came from the mouse, if the bit is set. If you look at RBIL, it says that this "mouse bit" is MCA specific, but this is no longer true. All PCs that support PS2 mice use this bit to indicate that the incoming byte was generated by the auxiliary PS2 input port.

但是你的代码是:

mouse_wait_data:
    ...
.a1:;jump into this loop until we rec a signal
    in al, 0x64 
    cmp al, 1
    jne .a1
    ...

所以你等到端口 0x64 设置为 1,但这意味着来自键盘的数据。总的来说,cmp 通常不是测试位的好选择,因为您永远不知道将来控制值将如何扩展,并且可能会有(斜体字的 MADE UP FICTIONAL EXAMPLE)new b7功能通过 1 无线 PS/2 设备供电发出信号,在这种情况下,b0 和 b5 可能仍会发出来自鼠标的可用数据信号,但你永远不会通过 cmp 和无线鼠标捕获它们,因为 b7 被意外设置一直.

代码应该更像:

    ...
.a1:;jump into this loop until we rec a signal
    in al, 0x64 
    and al, 0x21  ; mask b5 (mouse data) and b0 (data available)
    cmp al, 0x21  ; are both bits set?
    jne .a1       ; until some mouse data are available (throws away keyboard data!)
    ...

;#TODO: Find a way to make it so    #
;#  the mouse_wait_signal times out #

这太宽泛了,你已经设置好了吗PIT 8253/8254 chip, so you have some source of time, like the DOS int 8 system time ticks

那么最简单的方法可能就是使用这样的定时器滴答来实现超时机制。

没有计时器的其他方法(通常用于高级语言)是使用固定的静态计数器来将循环限制为 运行 如此多次,但具有非延迟汇编和之间的巨大差异CPU 速度,对于某些 CPUs 100k 循环可能是十分之一秒,而对于其他人来说,十亿只是百分之一秒,所以这在这里不适用,除非你找到一些可靠的来源延迟(比如即使在现代 PC 上读取 0x64 或 0x60 端口之一实际上也需要大量时间,那么固定计数器可能会起作用)。