- [kanwangxue] 感觉楼主很乖的。有点孩子气。呵呵。 01/27 08:58
- [kanwangxue] it界,进去干嘛啊,到时候自己牛比了,首先写一个自己的语言,自己用。进入IT界不就是随波做流吗/?他 01/27 08:57
- [kanwangxue] 哥们,不要为了赚钱而学计算机。 计算机是年轻时候干的, 30岁后可以开始想赚钱,年轻嘛,不要这么悲 01/27 08:50
- [游客] 怎么说? 01/26 16:22
- [游客] 你这不行啊,差远了! 01/10 22:29
- [chinatree] 谢谢你。相信你也会成功的。 01/09 14:22
- [landyking] 哥们儿,好久不见。相信你会成功的。 12/02 23:34
- [chinatree] 哇哇,被挖坟了。莫生气,只是感觉谦虚些好,就算你的程序真的是史上最强的,也别说出来嘛,自己偷着乐就行 11/20 00:41
- [xiaoyao2012] 你的程序和我的程序比较也不见得你的程序又节约空间,在某种意义上说你的程序用了没学的指令,所以不见得你 11/19 15:39
- [heliang6291] 一起加油啊 07/02 02:45
- [游客] 急需一个汇编程序大作业。。。。。。。。。。。。。。。。。。。??? 12/28 16:50
- [游客] 这么多人喜欢你,我嫉妒了。但你不可以喜欢那么多,允许你在我不需要你的时候帮别人。如果我需要立叫立到。 11/13 13:11
- [tily] 兄弟 我来看你啦 呵呵 最近可好呀 09/26 22:17
- [stqcw] 能加我qq吗?1270911891 我在做课程设计2的时候 遇到点问题 09/24 09:16
- [stqcw] 能加我qq吗?1270911891 我的环境还是有点问题。按下A的时候不能显示满屏的A 09/20 09:36
- [stqcw] 牛人 我在xp里面运行王爽 汇编第二版 p280的例子 按下esc键没反应 呀 怎样在虚拟机里配置一 09/17 15:18
- [landyking] 呵呵,交个朋友,共同学习. 09/08 00:03
- [luyingdzx] 能知道你的QQ吗?或者请加一下我的QQ271190440,可以吗 虽然在论坛能获得解答,但是有的问 08/07 21:32
[2012-05-27 10:02] 再发一个半成品<<俄罗斯方块>>
;;;;;;;;按键的扫描码
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
[ 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 ]
/冷汗,我都说是一个半成品的东西了,等待以后使用新算法重写。