组装鼠标 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 端口之一实际上也需要大量时间,那么固定计数器可能会起作用)。
好的,所以我从事汇编工作的时间足够长,足以理解体面的代码。
一直想把鼠标弄起来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 端口之一实际上也需要大量时间,那么固定计数器可能会起作用)。