汇编网首页登录博客注册
chinatree的学习博客
博客首页博客互动【做检测题】论坛求助

我的博客

个人首页 |  我的文章 |  我的相册 |  我的好友 |  最新访客 |  文章收藏 |  论坛提问 |  友情链接 |  给我留言  
图片载入中
学习动态
友情链接

[2012-05-27 10:02] 再发一个半成品<<俄罗斯方块>>

assume cs:code,ds:data,ss:stack,es:data
;;;;;;;;按键的扫描码
down         equ 50h
left         equ 4bh
right         equ 4dh
up                 equ 48h
ESCkey         equ 1
F1                 equ 3bh
F2                equ 3ch
space        equ 39h


levels                equ 9;放块种类个数
level                equ 11;等级速度调整
data segment 
;;;;定义方块形状,一个word的每4位是一个小方块的位置
tetris  dw 98ech,0,0cc7h,1,98ech,0,0cc7h,1,2;反z
                dw 18ebh,1,04c7h,0,18ebh,1,04c7h,0,3;z
                dw 447h, 0,994bh,0,14c7h,0,88cbh,0,4;反L
                dw 443h, 0,9970h,0,443h, 0,9970h,0,1;I
                dw 445h, 0,4cbh, 0,14c7h,1,996ch,0,5;L
                dw 94c7h,0,98ebh,0,446h, 0,94cbh,0,7;T
                dw 88c7h,0,88c7h,0,88c7h,0,88c7h,0,6;田
tetris1        dw 0,0,0,0,0,0,0,0,8eh                                ;一个点,有穿透属性
                dw 22h  ,0,84cbh,10h, 22h  ,  0,84cbh,10h,5h;...
;这里一tetris1为分界线,在它前的显示4次,从它往后都是5次,另外,颜色不许有第4位的高亮属性

nowdot                dw 0                ;位置y:x  当前显示的方块的位置
nowtetris  dw 0,0,0,0,0;当前方块的形状(2字),颜色,种类的指针,第几个子形状*4
nexttetris    dw 0,0,0,0,0;同nowtetris,下一个要显示的方块
        oldtetris dw 0,0,0,0,0
nowtime db 0;;;;                时间
mark        db 0,0;;;;                得到的分数
lptetris dw 0,18,36
                 dw 18*3,18*4,18*5
                 dw 18*6,18*7,18*8
                ;;;直接定址表,每个种类的偏移地址
color db 0;颜色
over db "GBABMBEBOBVBEBRB!B"
         db "RBeBsBtBaBrBtB BkBeByB(BYB)B B BQBuBiBtB B(BoBtBhBeBrB BaBnByB BkBeByB)B"
;;;;;;;;;游戏失败提示
quit db "QBuBiBtB?B B(BYB/BNB)B"
                ;ESC键退出提示
szlevel db "LEVEL:"
score        db "S@C@O@R@E@:@"
 winner db "Thank you for everyone.You are winner!$"
 helps  db 24," :deformation"
                db 25," :moves down "
                db 27," :moves left "
                db 26," :moves right"
                db   "space:pause   "
                db   "F1   : about  "
                db   "ESC  : exit   "
about        db "   About Tetris   "
        db "   Version  1.0   "
                db "  www.asmedu.net  "
                db "Copyright (c) 2012"
data ends


stack segment 
db 128 dup (?);;;;128字节栈
stack ends


code segment
oldint1ch         dw 0,0;旧int1ch的地址
time  db 0,0
timechar db 4,2,0
newint1c:
pushf          ;新1ch中断入口
call dword ptr cs:oldint1ch     ; 这里都是老程序了
inc cs:time
offlevel:
cmp cs:time,level;offlevel指向这个15来达到控制下落速度的目的
jb returnd
        mov cs:time,0
        inc cs:time+1
        call showtime
returnd:
iret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
showtime:
push ax                  ;主意不要寄存器冲突就好
push cx
push si
push di
push es
mov ax,0b800h
mov es,ax
mov di,1742
xor si,si
mov cx,3
mov ah,2
mov al,':'
mov es:[di+4],ax
mov es:[di+10],ax;先将两个":"显示出来
s1:push cx
mov cl,4
mov al,cs:timechar[si]
out 70h,al
in al,71h
mov ah,al
shr ah,cl
and al,0fh
add ax,3030h
mov es:[di],ah
mov ah,2
mov es:[di+1],ah
mov es:[di+2],ax
inc si
add di,6
pop cx
loop s1
pop es
pop di
pop si
pop cx
pop ax
ret

;  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;void paint proto lptetris:word,color:word
;功能:采取xor显示,在相同位置显示相同形状的方块,第一次是显示,第二次是清除
;        入口 : lptetris指向方块结构的指针,color方块的颜色
;        出口 :无
paint:
        push bp
        mov bp,sp
        push cx
        push bx
        push dx
        push si
        push di
        mov cx,4
        mov bx,[bp+4];方块指针
        mov ax,[bx]
        mov dx,[bp+6];颜色
        mov dh,1
        xchg dh,dl
        mov si,dx
        mov dx,[bx+2]
        cmp word ptr [bx+6],offset tetris1
        jb loop1
        mov cx,5
        loop1:
                push cx
                push dx
                push ax
                mov cx,5
                xor dx,dx
                and ax,31
                div cx
                mov bx,nowdot;当前位置
                add bl,dl
                add bh,al
                mov al,80
                mul bh
                mov di,ax;位置x=(ax&15)%4+nowdot低8位
                mov al,bl
                mov ah,0
                shl ax,1
                add di,ax;位置y=(ax%15)/4+nowdot高8位
                xor es:[di],si;
                pop ax
                pop dx
                call div32
                pop cx
        loop loop1
loop_2:
        pop di
        pop si
        pop dx
        pop bx
        pop cx
        pop bp
        ret 4
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;viod gettetris proto lptetris
;功能 :随机设置要显示的方块 
;入口 :指向4字指针(方块的形状,颜色,当前种类指针,第几个形状)
;返回 :无
;
gettetris:
        push bp
        mov bp,sp
        push bx
        push si 
        push cx
        mov si,[bp+4]
        in al,40h;;汇编没有rand函数,从40h端口读取一个字节当随机数,毕竟伪随机数的算法得好多代码
        mov ah,0
        mov cl,levels
        div cl
        xchg ah,al
        shl al,1
        mov ah,0
        mov bx,ax
        mov bx,lptetris[bx]
        mov [si+6],bx;种类指针
        push [bx+16];颜色
        pop [si+4]
        in al,40h
        mov ah,0
        mov cl,4
        div cl
        xchg ah,al
        shl al,1
        shl al,1
        mov ah,0
        mov [si+8],ax;第几个形状(*2)
        add bx,ax
        push [bx+2]
        push [bx]
        pop [si];形状
        pop [si+2];形状
        pop cx
        pop si
        pop bx
        mov sp,bp
        pop bp
        mov nowdot,107h;x:y
        ret 2
        
        
;<<<<<<<<<<<<<<<<<<<<<<<<<<<
;        bool canmovedot proto [bp+4]:位置
;canmove的穿透版,判断能否下落
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
canmovedot:
        push bp
        mov bp,sp
        push bx
        push di
        mov bx,[bp+4]
        cmp bh,23;不允许超过第23行
        ja @cannot
        mov al,80
        mul bh
        mov di,ax
        mov bh,0
        shl bx,1
        or bx,bx
        jz @cannot;第0列是边界线,不允许
        cmp bx,38
        ja @cannot;第20列是边界,不允许
        add di,bx
        inc di;测试的是颜色
@can1:
        test byte ptr es:[di],08
        jz @can;当前位置没有高亮属性,就可以返回允许(0标志)
        add di,80;测试下一行
        cmp di, 1900;不能超过第23行
        jb @can1
@cannot:
        mov ax,1;1 no
        jmp canret
@can:
        xor ax,ax;0 ok
canret:
        pop di
        pop bx
        mov sp,bp
        pop bp
        ret 2
        
        
        
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; bool canmove proto dot:[bp+4],lpmodel:[bp+6] 
;功能:判断给定位置能否显示给定形状
;入口: dot指定的位置,lpmodel指定形状指针
;出口: 如果可以显示返回0,否则返回1
canmove:
        push bp
        mov bp,sp
        push cx
        push bx
        push dx
        push di
        mov cx,4
        mov bx,[bp+6]
        mov ax,[bx]
        mov dx,[bx+2]
        or ax,ax
        jnz @l_oop1
        push [bp+4]
        call canmovedot
        jmp nret
@l_oop1:
        cmp word ptr [bx+6],offset tetris1+18
        jb l_oop1
        mov cx,5
        l_oop1:
                push cx
                push dx
                push ax
                mov cx,5
                xor dx,dx
                and ax,31
                div cx
                mov bx,[bp+4];当前位置
                add bl,dl
                add bh,al
                cmp bh,23
                ja l_oop3
                mov al,80
                mul bh
                mov di,ax;位置x=(ax&31)%5+nowdot低8位
                mov al,bl
                mov ah,0
                shl ax,1
                or ax,ax
                jz l_oop3
                cmp ax,38
                ja l_oop3
                add di,ax;位置y=(ax%31)/5+nowdot高8位
                test byte ptr es:[di+1],8;
                jz l_oop2
        l_oop3:        mov ax,1
                        add sp,6
                        jmp nret
        l_oop2: 
                pop ax
                pop dx
                call div32;ax>>=5
                pop cx
        loop l_oop1
nret:
        pop di
        pop dx
        pop bx
        pop cx
        pop bp
        ret 4
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
div32:
push bx
push ax
mov ax,dx
xor dx,dx
mov cx,32
div cx
mov bx,ax
pop ax
div cx
mov dx,bx
pop bx
ret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; void movewindow proto
;功能:把上一行(x-1)复制到当前行x
;入口:无
;出口:无
movewindow:
        push cx
        push di
        push bx
        push ds
        push es
        pop ds
        push bp
        mov bp,sp
        mov cx,[bp+12];;取testtetris函数的当前行cx值
        pop bp
        dec cx
        moveloop:
                push cx
                mov cx,38
                mov di,39
                lea si,[bx+di-80]
                lea di,[bx+di]
                std
                rep movsb
                pop cx
                sub bx,80
        loop moveloop
        mov cx,38
        mov al,0
        mov di,82
        cld
        rep stosb;第一行填0
        pop ds
        inc mark
        pop bx
        add bx,80
        pop di
        pop cx
        ret
                
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;void testtetris proto
;功能:判断是否可以得分,如果可以,就清除满的那行,并让上面的"砖头 落"下来
;入口 无
;出口 无
testtetris:
        push cx
        push di
        push bx
        mov bx,1840
        mov di,39
        mov cx,23
@loop:
        push cx;;如果会调用movewindow函数,这个值会被movewindow从栈中复制
        mov cx,18
        @loop1:
                test byte ptr es:[bx+di],8
                jz @loop2
                sub di,2
                loop @loop1
                call movewindow
        @loop2:
                pop cx
                sub bx,80
                mov di,39
        loop @loop
        pop bx
        pop di
        pop cx
        ret
;<<<<<<<<<<<<<<<
;void printfc void
;显示分数
printfc:
        push bx
        push di
        mov di,1270;显示位置
        mov al,mark
        mov ah,0
        mov bl,5
        div bl
        cmp al,1
        jnz @p1;;;;;;;;;;;;设置速度
        mov byte ptr cs:[offlevel+5],level-3
        mov word ptr es:[1424],432h
        jmp @p4
@p1:
        cmp al,2
        jnz @p2
        mov byte ptr cs:[offlevel+5],level-5
        mov word ptr es:[1424],433h
        jmp @p4
@p2:
        cmp al,3
        jnz @p3
        mov byte ptr cs:[offlevel+5],level-7
        mov word ptr es:[1424],434h
        jmp @p4
@p3:
        cmp al,4
        jnz @p4
        mov byte ptr cs:[offlevel+5],level-8
        mov word ptr es:[1424],435h
@p4:
        mov al,mark
        mov bl,10 
@p:
        mov ah,0
        div bl
        add ah,30h
        mov byte ptr es:[di],ah
        mov byte ptr es:[di+1],4
        or al,al
        jz retret
        dec di;倒序显示
        dec di
        jmp @p 
retret:
        pop di
        pop bx
        ret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;void setint1ch proto void
;设置1c中断
setint1ch:
        push es
        xor ax,ax
        mov es,ax
        push es:[1ch*4]
        pop cs:oldint1ch
        push es:[1ch*4+2]
        pop cs:oldint1ch+2
        cli 
        mov word ptr es:[1ch*4],offset newint1c
        mov es:[1ch*4+2],cs
        sti
setret:
        pop es
        ret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;;程序开始
main:
        mov ax,stack
        mov ss,ax
        mov sp,128
        mov ax,data
        mov ds,ax
        xor ax,ax
        int 10h;设置屏幕40*25
        mov ah,1
        mov ch,20h
        int 10h;不显示光标
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        mov ax,0b800h
        mov es,ax
        call init
        mov ax,offset nexttetris
        push ax
        call gettetris
        mov nowdot,0945h
        push nexttetris+4
        mov ax,offset nexttetris
        push ax
        call paint;显示 "下一个"方块
        mov ax,offset nowtetris
        push ax
        call gettetris
        push nowtetris+4
        mov ax,offset nowtetris
        push ax
        call paint;显示当前方块
        mov al,cs:time+1
        mov nowtime,al;获得当前秒数
startthis:
        mov al,cs:time+1
        cmp al,nowtime;获得当前秒数,并和nowtime比较,不同就可以下落了
        jnz @3
        jmp  @2
@3:                ;时间到了,是时候往下"落"了
        mov nowtime,al
        mov ax,offset nowtetris
        push ax
        mov ax,nowdot
        inc ah;
        push ax
        call canmove;判断可以"落"不
        or ax,ax
        jnz @1
        push nowtetris+4;清除当前显示
        mov ax,offset nowtetris
        push ax
        call paint
        inc byte ptr nowdot+1;"落"一行
        push nowtetris+4
        mov ax,offset nowtetris
        push ax
        call paint;显示
        
        jmp @2
@1:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;到底了
        push nowtetris+4
        mov ax,offset nowtetris
        push ax
        call paint;清除当前显示
        mov ax,15
        push ax
        mov ax,offset nowtetris
        push ax
        call paint;;;;;;改变颜色(前景高亮+白色)
        mov al,mark
        push ax
        call testtetris;判断是否可以得分 
        pop ax
        mov ah,mark
        sub ah,al
        jz tests
        dec ah
        add mark,ah
tests:
        call printfc
        mov al,mark
        cmp al,250
        jb @next@1
        call @winner
@next@1:
        push es
        push ds
        pop es
        mov si,offset nexttetris
        mov di,offset nowtetris
        mov cx,10
        cld
        rep movsb;把下一个方块给当前方块
        pop es
        mov nowdot,0945h
        push nexttetris+4
        mov ax,offset nexttetris
        push ax
        call paint;清除"下一个"方块

        mov ax,offset nexttetris
        push ax
        call gettetris
        push nowdot
        mov nowdot,0945h
        push nexttetris+4
        mov ax,offset nexttetris
        push ax
        call paint;;;;;;;;显示"下一个"方块
        
        pop nowdot
        push nowtetris+4
        mov ax,offset nowtetris
        push ax
        call paint;显示当前方块

        mov ax,offset nowtetris
        push ax
        mov ax, nowdot;
        inc ah
        push ax
        call canmove
        or ax,ax;;;如果刚显示出来,但是不能往下"落",表示下面的方块很高了,要结束了
        jnz restart;不能下了就结束了
        
@2:
        mov ah,11;判断用户是否按键了
        int 21h
        or al,al
        jnz @5;按了就读出按键的扫描码和ascii
        jmp near ptr startthis
@5:
        xor ax,ax
        int 16h
        call dispatch;处理按键
        jmp startthis
restart:;;;;;失败了
        mov al,0
        xor di,di
        mov cx,4000
        cld
        rep stosb
        lea si,over;显示失败信息
        mov di,12*80+28
        MOV CX,18
        rep movsb
        add di,118
        mov cx,72
        rep movsb
        xor ax,ax
        int 16h;按Y再玩一次
        cmp ah,15h
        jnz codeend
        jmp main
codeend:
call quitgame
;<<<<<<<<<<<<<<<<<<<<<<<<<<<
;void @winner proto void
;显示胜利信息并退出
@winner:
        mov ax,400h
        xor di,di
        mov cx,1000
        cld
        rep stosw
        mov si,offset winner
        mov ah,2
        mov di,13*80+2
        mov cx,38
        cld
        @win:
                lodsb
                stosw
        loop @win
        mov ah,7
        int 21h
        call quitgame
        ret
;<<<<<<<<<<<<<<<<<<<<<
;viod init proto
;功能:设置屏幕,"画"界线
;入口:无
;返回:无
init:
        push cx
        push di
        push es
        xor ax,ax
        mov es,ax
        mov cx,es:[1ch*4+2]
        mov ax,cs
        pop es
        cmp ax,cx
        jz @init1;如果中断已经设过,就不再设置
        call initwindow;欢迎界面
        call setint1ch;设置中断
@init1:
        mov cx,1000
        xor di,di
        mov ax,di
        cld
        rep stosw
        mov si,offset score;显示"score"
        mov di,1250
        mov cx,12
        rep movsb
        mov cx,6
        mov di,1410
        mov si,offset szlevel;显示"level:"
        mov ah,10
        cld
        @init:
                lodsb
                stosw
        loop @init
        mov word ptr es:[di+2],431h;等级
        call help;显示按键信息
        call interface;画可移动区域
        mov mark,0;分数
        mov byte ptr cs:[offlevel+5],level;设置初始等级下落速度
        call printfc;显示分数
        pop di
        pop cx
        ret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
initwindow:
        push ds
        push si
        push di
        push cx
        push bx
        call draw
        db "TTTTT   EEEEE   TTTTT   RRRR   III   SSS"
        db "  T     E         T     R  R    I    S  "
    db "  T     EEEEE     T     RRRR    I     S "
        db "  T     E         T     R R     I      S"
        db "  T     EEEEE     T     R  R   III   SSS"
  @name db "by chinatree"
  @data db "Copyright (c) 2012  www.asmedu.net"
draw:
        pop si;上面字符的首地址
        mov color,0
        push cs
        pop ds
        mov di,720
        cld
        mov cx,200
        @draw:
                lodsb
                mov ah,al
                xor ah,75h
                stosw
        loop @draw;TETRIS这几个大字母
        mov cx,12
        mov ah,3h
        mov di,1550
        cld
        @draw3:
                lodsb
                stosw
        loop @draw3;显示"by chinatree"
        mov cx,34
        mov di,1606
        cld
        @draw4:
                lodsb
                stosw
        loop @draw4;显示"Copyright (c) 2012..."
        mov cx,2
        @draw2:
                push cx
                mov cx,0
                @draw6:
                        mov ah,11
                        int 21h
                        or al,al
                        jnz @draw1
                loop @draw6;判断用户是否按键了,如果按了,就返回,没按就延时
                pop cx
        loop @draw2
        jmp @draw7
        @draw1:
        xor ax,ax
        int 16h
        pop cx;Illegal use of CS register
        @draw7:
        pop bx
        pop cx
        pop di
        pop si
        pop ds
        ret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;void interface proto
;功能;画出方块移动范围
;入口:无
;返回:无
interface:
        push di
        push cx
        xor di,di
        mov ax,77dbh
        mov cx,40
        cld
        rep stosw
        mov cx,23
@s:
        mov es:[di],ax
        mov es:[di+40],ax
        mov es:[di+78],ax
        add di,80
        loop @s
        mov cx,40
        rep stosw
        pop cx
        pop di
        ret
;<<<<<<<<<<<<<<<<<<<<<
;viod quitgame proto void
;退出
quitgame:

        mov ax,2
        int 10h
        mov ax,0b800h
        mov es,ax
        mov ax,720h
        mov cx,2000
        xor di,di
        cld 
        rep stosw
        xor ax,ax
        mov es,ax
        cli
        push cs:oldint1ch;把原来的中断还设回去
        pop es:[1ch*4]
        push cs:oldint1ch+2
        pop es:[1ch*4+2]
        sti
        mov ax,4c00h
        int 21h 
;<<<<<<<<<<<<<<<<
;void help proto
;功能:显示帮助和版本信息
;入口:无
;出口:无
help:
        push cx
        push di
        mov si,offset helps
        mov di,208
        mov cx,7
        mov ah,6
        @loop@:
                push cx
                mov cx,14
                @lloop:
                        lodsb
                        stosw
                loop @lloop
                pop cx
                add di,52
        loop @loop@
        pop di
        pop cx
        ret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;void abouts proto void
;显示版本信息
abouts:
        push es
        push ds
        push si
        push di
        push cx
        
        push ds
        
        push es
        pop ds
        xor si,si
        mov di,2000
        mov cx,di
        cld
        rep movsb
        xor di,di
        mov ax,di
        mov cx,1000
        rep stosw
        pop ds
        mov si,offset about
        mov ah,6
        mov di,904
        mov cx,4
        @loop1@:
                push cx
                mov cx,18
                @loop2@:
                        lodsb
                        stosw
                loop @loop2@
                pop cx
                add di,44
        loop @loop1@
        mov ah,7
        int 21h
        push es
        pop ds
        xor di,di
        mov cx,2000
        mov si,cx
        cld 
        rep movsb
        pop cx
        pop di
        pop si
        pop ds
        pop es
        ret
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;viod dispatch proto
;功能判断用户是否按下了一些功能键并处理,不是就不处理
;入口:ax=扫描码(高16位):ascii(低16位)
;出口:无
dispatch:
        cmp ah,left;处理左键
        jnz next1
        mov ax,offset nowtetris
        push ax
        mov ax,nowdot
        dec al
        push ax
        call canmove
        or ax,ax 
        jnz @l77
        push nowtetris+4
        mov ax,offset nowtetris
        push ax
        call paint
        dec byte ptr nowdot;位置x-=1
        push nowtetris+4
        mov ax,offset nowtetris
        push ax
        call paint
@l77:
        ret
next1:
        cmp ah,up;上键
        jnz next2
        push es
        push ds
        pop es
        mov si,offset nowtetris
        mov di,offset oldtetris
        mov cx,10
        cld
        rep movsb
        pop es
        mov bx,offset nowtetris
        mov cx,[bx+6]
        mov ax,[bx+8]
        add ax,4
        mov bl,16
        div bl
        xchg ah,al
        mov ah,0
        mov bx,ax
        mov nowtetris+8,ax
        add bx,cx
        push [bx]
        pop nowtetris
        push [bx+2]
        pop nowtetris+2
        mov ax,offset nowtetris
        push ax
        push nowdot
        call canmove
        or ax,ax
        jz @llll
        push es
        push ds
        pop es
        mov di,offset nowtetris
        mov si,offset oldtetris
        mov cx,10
        cld
        rep movsb
        pop es
        jmp near ptr return
@llll:
        push oldtetris+4
        mov ax,offset oldtetris
        push ax
        call paint;消除当前方块
        push nowtetris+4
        mov ax,offset nowtetris
        push ax
        call paint
        ret
next2:
        cmp ah,right;右键
        jnz next3
        mov ax,offset nowtetris
        push ax
        mov ax,nowdot
        inc al
        push ax
        call canmove
        or ax,ax 
        jnz @l9
        push nowtetris+4
        mov ax,offset nowtetris
        push ax
        call paint
        inc byte ptr nowdot;位置x+=1
        push nowtetris+4
        mov ax,offset nowtetris
        push ax
        call paint
@l9:
        ret
next3:
        cmp ah,down;下键
        jnz next4
        mov ax,offset nowtetris
        push ax
        mov ax,nowdot
        inc ah
        push ax
        call canmove
        or ax,ax 
        jnz retur
        push nowtetris+4
        mov ax,offset nowtetris
        push ax
        call paint
        inc byte ptr nowdot+1;位置y+=1
        push nowtetris+4
        mov ax,offset nowtetris
        push ax
        call paint
        retur:
        ret
next4:
        cmp ah,space;空格键,暂停程序
        jnz next5
        @next@2:
        xor ax,ax
        int 16h
        cmp ah,F1;暂停时只支持显示版本的F1
        jnz @next_1
        call dispatch;递归一次
        jmp @next@2
        @next_1:
        cmp al,32
        jnz @next@2
        mov al,cs:time+1
        mov nowtime,al
        ret
next5:
        cmp ah,F1;F1显示帮助
        jnz next7
        call abouts
        ret
next7:
        cmp ah,ESCkey;ESC退出
        jnz return
        push ds
        push ds
        
        push es
        pop ds
        mov di,1000h
        mov cx,1000
        xor si,si
        cld
        rep movsw
        xor ax,ax
        mov cx,1000
        mov di,ax
        cld
        rep movsw
        pop ds
        mov si,offset quit
        mov di,990
        mov cx,22
        rep movsb
        xor ax,ax
        int 16h
        cmp ah,15h
        jz return1;;;;Y退出
        push es
        pop ds
        mov si,1000h
        mov cx,1000
        xor di,di
        cld
        rep movsw
        pop ds
        jmp return
return1:
        call quitgame
return: 
ret

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
code ends
end main
评论次数(5)  |  浏览次数(884)  |  类型(汇编作业) |  收藏此文  | 

[  chinatree   发表于  2012-05-27 10:03  ]

MASM提示Extra characters on line:
先看下那行是否有多余的字符,如果没有,查看下文件的编码方式,UTF-8等编码会在文件的开始部分加上2个字节的标志,只有ANSI编码不会添加任何东西.

windows 定时器浅析:
PC中有个8253/8254定时器,实模式下可以使用40h~43h端口来访问或控制.40h端口是一个字,它的值是计数值,并且是递减的,初始值为65535.由于它的值一直在变,所以需要先锁定再读取,例:
mov al,0
out 43h,al
in al,40h
mov ah,al
in al,40h
xchg ah,al
得到的这个值的单位是840纳秒,比较小,当它跑一圈时是65536*840约55毫秒,且每跑一圈会触发int 8中段,进行一些操作(网上零碎的说法是刷新内存),在int 8中有条指令:int 1ch,这个是留给程序员的编程接口,在初始化时这个中断中只有一条iret指令.这两个中断每秒调用1000/55约18.2次.注意如果需要截获int 1ch,最好使此中断运行时间不超过10毫秒.另外此计时器有6种工作方式,详细请参阅中国科技大学<<微机原理>>.



1,假如第24行和第23行全是方块,在调用testdiamond函数时,会先调用movewindow清除第24行,结果就是把第23行给了第24行,然后去检测第23行(没清除前的第22行),这样当前的第24行会被漏掉.
2,显示带穿透效果的那个方块时,由于定义成0000h的形式,在paint函数中的显示时,每次显示的都是那一个点,由于采用的是xor来显示,这样第一次xor时显示,第2次消除,3显示,4清除,结果发现会出现一个空的方块,我解决的办法是根据方块形状值来有针对的显示.形状值为0时只xor一次.
现在改了,由于可以显示5次,这样虽然xor了5次,浪费了些,但是可以让代码量小些,感觉也足够了.
3,必须针对穿透属性的方块增加一中判断函数,判断方式就是给定一个位置,如果它往下能下就直接返回0表示允许,不能下时循环判断当前位置这一列往下是否有空缺的方块位置,有就返回0表示允许.
4,对于空格暂停,不能使用ah=7/int21h来做.因为它不能处理ascii为0的按键,会对按键进行递归操作.
5,改版了以前显示的方式,改为5位表示一个相对位置,并写了个段代码用于输入相对位置,得到一个数据,tc下通过:
        #include <stdio.h>
int main()
{
        int i[5];
        int j,l;
        long k;
        while (scanf("%x %x %x %x %x",i,i+1,i+2,i+3,i+4))
        {                                        /*当然这里只能输入字母等能退出了*/
                                        /*输入比如,10 11 12 21 20这样,xy xy xy xy xy,当然这里是相对坐标*/
                for(j=0,k=0;j<5;j++)
                {
                        l=i[j]&15;
                        l+=(i[j]>>4)*5;
                        k<<=5;
                        k|=l;
                }
                printf("%lX\n",k);/*x大写表示显示的a~f用大写表示哦*/
        }
        return 0;
}
第一次使用自己写的代码来帮自己解决另外的一些问题,虽然比较丑陋,但是有点不一样的感觉.
6,由于使用的是判断颜色是否高亮来确定是否可以移动,定义时不能有高亮颜色位存在,否则动不了.如果使用别的方法来判断,还没有想出.不然就可以落底后不变色了.
7,对于设置等级,我把它放到了显示分数的代码块中,因为只有每个方块到底后才会调用那块代码来刷新.
8,当清除某一行时,不能忘记把最上行用0填充掉.不然会有个bug,虽然比较深.
9,为判断,显示这俩函数增加了个不除法溢出的模块,因为在右移5位时,有可能发生除法溢出,shl等指令又不能把dx:ax当成一个整体.
10,方块的下落速度是由自定义的int1ch来操作的.每秒被调18.2次,每次将某个变量加1,再判断是否可以"进位",需要进位就把另一变量加1,当主函数比较时间时,发现不同了,就是时间到了,该下落了.但是在失败后重新开始时,要进行判断,不要重复设置中断,以及开始画面,开始画面在整个进程的生命周期中只需要出现一次.
11,退出时不要忘记把中断还设回去,因为并没有安装,中断体还在自己的代码段,有可能会被后面的进程覆盖,那样系统就崩溃了.
12,随机函数还是蛮重要的,它和每种方块出现的频率有关,有时会连续出现几个相同的方块,有时间我要找个公式做个随机函数出来
13,把程序模块化是很有必要的,还有缩进格式.
14, lea指令的妙用:
lea的功能就是把源操作数[]内的表达式求值并把这个值给目的操作数.正因为这个特性,用它来做加法是非常简单的,如lea ax,[bx+si+100]就是ax=bx+si+100,这比add指令要方便吧,呵呵.

[  fpamc   发表于  2012-05-27 10:56  ]

`(*∩_∩*)′

[  游客   发表于  2012-05-27 18:17  ]

厉害,顶!!!

[  tomato   发表于  2012-05-27 23:22  ]

代码好多啊!看了之后能唬人!你这算是高手了。

[  chinatree   发表于  2012-05-27 23:41  ]

/冷汗,我都说是一个半成品的东西了,等待以后使用新算法重写。

 
 请输入验证码  (提示:点击验证码输入框,以获取验证码