| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 7330 人关注过本帖, 1 人收藏
标题:贴一个简单的滑鼠程式
取消只看楼主 加入收藏
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
结帖率:100%
收藏(1)
已结贴  问题点数:20 回复次数:5 
贴一个简单的滑鼠程式
应zhulei1978班竹的呼吁,贴个原创代码。

这是一个滑鼠操作的简单程式,但不是win32的视窗程式,是dos的16bit。
许多大学的汇编教材,还停留在三十年前的dos年代,地址还是段:移偏,
永远是一个黑框,永远是2、10、16进制转换,永远是印几个烂字符,
能够改变颜色已经进阶级别了。

就我来看,学汇编是学它的灵活性,学它对地址的运用,只要你理解CPU
是如何定址,如何间接定址,如何间接再间接定址,那么C,C++常为人诟病的
指针就会不说自明。

鼠标操作在win32是挺简单的,只要在消息串列里拿到
WM_MOUSEMOVE  鼠标移动,将参数lParam变换为x,y坐标就知道鼠标的位置
WM_RBUTTONDOWN ;右键按下
WM_LBUTTONDOWN ;左键按下
完事了,根据程式要和鼠标位置做事。

可是,大家忘了DOS里其实也可以操作鼠标,我猜,许多学了一整季汇编的学生,
还不知道有鼠标的存在。翻了几页论坛的贴,似乎找不到一个操作鼠标的程式。

好吧,我来抛砖引玉(很耳熟啊),发一个本人初学汇编时的一个练习。

这程式利用了一些MASM定义的宏,主要是BIOS对光标的操作。
INT 33H是DOS的标准滑鼠操作中断
ax=0,检查安装与否
ax=1,显示滑鼠指标
ax=2,隐藏滑鼠指标
ax=3,取得滑鼠位置

编译方法:
copy代码存成ANSI标准文字档格式,档名任意,可叫作pickme.asm
本程式是com格式
masm 5.x :
 masm pickme.asm
 link pickme.obj pickme.exe
 exe2bin pickme.exe
 del pickme.exe

masm 6.x
ML /AT pickme.asm


运行程式:
在windows/dos下,或dosbox或虚拟dos,或纯dos下(需安装滑鼠驱动)
键入pickme [String]  
[String] 可以是任意字符串,比如hello world, i am a boy, you are a girl 之类
然后:
1把鼠标移到字符串的上方,按左键不放
2.拖拉到任意位置,松开左键丢下字符串
3. 重复1,直到你玩厌了,按ESC离开


代码很短,写了简短解释,因为那时初学,程式写得很烂,没什么高探技术。

程式也没多大用途,只是一个汇编练习,当它是个玩意就不会闷。

图片附件: 游客没有浏览图片的权限,请 登录注册



二楼发代码。


[此贴子已经被作者于2016-6-16 10:06编辑过]

搜索更多相关主题的帖子: 大学 如何 
2016-06-16 09:59
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
代码:

程序代码:
read_buf        equ     0C0h
paramater_L     equ     64

; -------------MASM Marco definition start ---------------------

@GetCur        MACRO    page ;读取光标位置
        IFNB    <page>
        mov    bh,page
        ELSE
        xor    bh,bh
        ENDIF
        mov    ah,03h
        int    10h
        ENDM

@SetCurPos    MACRO    column,row,page ;设定光标位置
        IFNB    <column>
        mov    dl,column
        ENDIF
        IFNB    <row>
        mov    dh,row
        ENDIF
        IFNB    <page>
        mov    bh,page
        ELSE
        xor    bh,bh
        ENDIF
        mov    ah,02h
        int    10h
        ENDM

@GetChAtr    MACRO    page ;读取光标属性
        IFNB    <page>
        mov    bh,page
        ELSE
        sub    bh,bh
        ENDIF
        mov    ah,08h
        int    10h
        ENDM

@SetCurSz    MACRO    first,last  ;设定光标大小
        mov    ch,first
        mov    cl,last
        mov    ah,01h
        int    10h
        ENDM

@PutChAtr    MACRO    char,atrib,page,repeat ;显示颜色字节
        IFNB    <char>
        mov    al,char
        ENDIF
        IFNB    <atrib>
        mov    bl,atrib
        ENDIF
        IFNB    <page>
        mov    bh,page
        ELSE
        xor    bh,bh
        ENDIF
        IFNB    <repeat>
        mov    cx,repeat
        ELSE
        mov    cx,1
        ENDIF
        mov    ah,09h
        int    10h
        ENDM

; -------------MASM Marco definition end ---------------------


COD             segment
                assume  cs:cod, ds:cod,es:cod
                org     100h
start:          jmp     begin

msg_L           db      0
first_pos       dw      0
exit_flag       db      0
attrib          db      0
column          dw      ?
row             dw      ?
press           dw      0
cur_size        dw      0
cur_pos         dw      0
msg_x           db      0
msg_y           db      0
errmsg          db      "No mouse installed !",10,13,'$'
help            db      'Usage : Pickme [String]',10,13,'$'

begin:          mov     ax,0                   ;check mouse install
                int     33h                    ;mouse int
                cmp     ax,0ffffh              ;installed
                jz      go                     ;yes, continue
                mov     dx,offset errmsg
quit:           mov     ah,09h
                int     21h
                jmp exitX      ;quit to dos

go:             mov     si,80h  ;指向psp参数输入区,即紧贴程式后的输入
                lodsb
                or      al,al
                jnz     go2
go1:            mov     dx,offset help
                jmp     quit
go2:            cmp     al,paramater_L
                ja      go1
                mov     cl,al
                mov     msg_L,al
                xor     ch,ch
                mov     bl,cl
                xor     bh,bh
                mov     byte ptr [bx+si],0      ;0 overwrite 0dh
                xor     bp,bp
go3:            lodsb
                cmp     al,' '
                jnz     go4
                inc     bp
                loop    go3
go4:            dec     si
                dec     si
                mov     first_pos,si
                mov     byte ptr [si],' '
                mov     al,msg_L
                xor     ah,ah
                sub     ax,bp
                inc     ax
                mov     msg_L,al
                @GetCur                        ;get cursor
                mov     cur_size,cx            ;store cursor size
                mov     cur_pos,dx
                dec     dh
                mov     msg_y,dh
                mov     di,0c0h
                mov     cx,paramater_L
                mov     dl,0
go10:           @setCurPos dl,dh
                @GetChAtr
                stosb
                inc     dl
                loop    go10
                mov     cx,paramater_L
                xor     bp,bp

go11:           push    cx
                mov     cl,msg_L
                mov     ch,0
                mov     di,first_pos
                mov     si,0c0h
                add     si,bp
                repe    cmpsb           ;compare ds:si and es:di
                jz      go12
                pop     cx
                inc     bp
                loop    go11
                mov     word ptr msg_x,0
                jmp     go13

go12:           pop     cx
                sub     cx,paramater_L
                neg     cx
                mov     msg_x,cl

go13:           @SetCurSz 30h,31h              ;hidden cursor

                @SetCurPos msg_x,msg_y
                call    read_msg
                mov     si,first_pos
                mov     attrib,70h  ;反白
                call    dispstr
                mov     ax,1                   ;display mouse cursor
                int     33h
                mov     ax,8
                mov     cx,0
                mov     dx,23*8                ;max mouse vertial move
                int     33h

restart:        mov     ah,06h                 ;keyboard
                mov     dl,0ffh                ;input mode
                int     21h
                jz      j5
                cmp     al,1bh                 ;press <esc>
                jnz     j5
                mov     exit_flag,1
                jmp     draw

j5:             mov     ax,3                   ;get mouse status
                int     33h
                shr     dx,1                   ;dx / 8 + 1
                shr     dx,1
                shr     dx,1
                mov     row,dx                   ;取列
                shr     cx,1                   ;cx / 8 + 1
                shr     cx,1
                shr     cx,1
                mov     column,cx                ;取行
                cmp     bx,1
                jz      j10
                mov     press,0

j10:            cmp     press,1
                jnz     j20
                cmp     cl,msg_x
                jnz     draw
                cmp     dl,msg_y
                jz      restart
                jmp     draw

j20:            cmp     dl,msg_y
                jnz     restart
                cmp     cl,msg_x
                jb      restart
                mov     al,msg_x
                add     al,msg_L
                cmp     cl,al
                ja      restart
                cmp     bx,1
                jnz     restart
                mov     press,1


draw:           @SetCurPos msg_x,msg_y
                mov     si,read_buf
                mov     attrib,07h
                call    dispStr
                cmp     exit_flag,1
                jz      exit
                mov     ax,column
                mov     msg_x,al
                mov     ax,row
                mov     msg_y,al
                @SetCurPos msg_x,msg_y
                call    read_msg
                mov     si,first_pos
                mov     attrib,70h
                call    dispstr
                jmp     restart

exit:           mov     ax,2                   ;hide mouse cursor
                int     33h

                mov     cx,cur_size
                @SetCurSz ch,cl
                mov     dx,cur_pos
                dec     dh
                @SetCurPos dl,dh
exitX:          mov     ah,4ch                 ;end program
                int     21h
;----------------------------------------------------------------------------------
read_msg:       push    ax
                push    bx
                push    cx
                push    dx
                push    di
                push    word ptr msg_x
                mov     cl,msg_L
                xor     ch,ch
                mov     di,read_buf     ;psp 0C0h
read1:          push    cx
                @GetChAtr
                stosb                   ;store to 0c0h
                inc     msg_x
                @SetCurPos msg_x,msg_y
                pop     cx
                loop    read1
                mov     al,0
                stosb
                pop     word ptr msg_x
                @SetCurPos msg_x,msg_y
                pop     di
                pop     dx
                pop     cx
                pop     bx
                pop     ax
                ret
;----------------------------------------------------------------------------------
DispStr:        @GetCur
ds1:            lodsb
                or      al,al
                jz      ds_exit
                @PutChAtr al,attrib
                inc     dl
                @SetCurPos dl,dh
                jmp     ds1
ds_exit:        ret
;----------------------------------------------------------------------------------

cod             ends
end             start



[此贴子已经被作者于2016-6-16 17:48编辑过]

2016-06-16 10:00
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
回复 4楼 zhulei1978
谢谢班竹加亮


大家若有疑问或意见,欢迎提出讨论
2016-06-16 17:52
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
回复 6楼 zhulei1978
dos为com/exe程式前保留100h空间,80h之前是系统资料,之后是参数区(80h-100h)。
没规定程式不可利用这块小空间(80h-100h),0ch就是随便找一块足够大的內存放程式资料。
好像很小家子气,但这在dos比较宽松的环境是挺常见。
2016-07-07 14:34
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
回复 10楼 zhulei1978
对啊,就是要把SI移到第一个字符的前一个位置,所以要减SI二次。
顺便提一下,SUB SI,2虽然一句,机器码长3bytes,两次DEC SI都不过是2byte长。
2016-07-11 07:48
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
说来话长…

当键入c:\> pickme  I like this book <按回车>
你会看见I like this book立即变成反白,但实际操作不是如此简单,当按回车后,光标会下移一列,且回到最前

pickme  I like this book <按回车>
_

我们可以把光标上移一行(回到输入行),但问题是,谁知道光标的x坐标,因为文件夹的位置不确定。

c:\>pickme  I like this book
c:\data>pickme  I like this book
c:\data\myprogram\masm>pickme  I like this book

按了回车后,只知道光标被下移一行,回到最前,然而[I like this book]在该行的哪儿?

要找到x坐标,做法是:
1.上移一行(dh-1)
2.光标移到最前(dl=0)
3.设定光标
4.读取光标位置的字符,放到c0处,dl+1(光标右移),c0+1(储存字串缓冲+1)
5,回到3,直到读完64bytes(我们的限制)
6.这时候,读入整行如下:
c:\data>pickme  I like this book
7.然后,设定x坐标=0
8.由c0开始,和参数区(约82h开始)的字符串比较,不同则c0+1,x坐标+1,再比较,直至找到相同。
9.最后的x坐标值就是 [c:\data>pickme]  之后的位置,再做反白,就像你看见的行为。




[此贴子已经被作者于2016-7-11 10:58编辑过]

2016-07-11 10:52
快速回复:贴一个简单的滑鼠程式
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.113267 second(s), 12 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved