assume cs:code,ds:data,ss:stack
data segment
;**********************************************************************************************************
;**********************************************************************************************************
;**********************************************************************************************************
BOUNDARY_COLOR dw 1131H
NEXT_ROW dw 160
SNAKE_HEAD dw 0
SNAKE_STERN dw 12
SNAKE_COLOR dw 2201H
SNAKE dw 200 dup (0,0,0)
NEW_NODE dw 18
FOOD_LOCTION dw 160*5 + 30*2
FOOD_COLOR dw 4439H
UP db 48H
DOWN db 50H
LEFT db 4BH
RIGHT db 4DH
BACK_GROUND_COLOR dw 0700H
DIRECTION dw 3 ;up 0 down 1 left 2 right 3
DIRECTION_FUNTION dw OFFSET isMoveUp - OFFSET greedy_snake + 7E00H ; 0
dw OFFSET isMoveDown - OFFSET greedy_snake + 7E00H ; 1
dw OFFSET isMoveLeft - OFFSET greedy_snake + 7E00H ; 2
dw OFFSET isMoveRight - OFFSET greedy_snake + 7E00H ; 3
;**********************************************************************************************************
;**********************************************************************************************************
;**********************************************************************************************************
data ends
stack segment stack
db 128 dup (0)
stack ends
code segment
start: mov ax,stack
mov ss,ax
mov sp,128
call sav_old_int9
call set_new_int9
call cpy_greedy_snake
mov bx,0
push bx
mov bx,7E00H
push bx
retf
mov ax,4C00H
int 21H
;================================================================
greedy_snake: call init_reg
call clear_screen
call init_screen
call init_direction
call init_food
;nextDelay: call delay
; cli
; call isMoveDirection
; sti
; jmp nextDelay
testA: mov ax,1000H
jmp testA
mov ax,4C00H
int 21H
;================================================================
init_food: mov si,FOOD_LOCTION
mov dx,FOOD_COLOR
mov es:[si],dx
ret
;================================================================
isMoveDirection:
mov bx,DIRECTION
add bx,bx
call word ptr ds:DIRECTION_FUNTION[bx]
ret
;================================================================
delay: push ax
push dx
mov dx,9000H
sub ax,ax
delaying: sub ax,1000H
sbb dx,0
cmp ax,0
jne delaying
cmp dx,0
jne delaying
pop dx
pop ax
ret
;================================================================
init_direction:
mov DIRECTION,3
ret
;================================================================
new_int9: push ax
in al,60H
pushf
call dword ptr cs:[200H]
cmp al,UP
je isUp
cmp al,DOWN
je isDown
cmp al,LEFT
je isLeft
cmp al,RIGHT
je isRight
cmp al,3BH
jne int9Ret
call change_screen_color
int9Ret: pop ax
iret
;================================================================
isUp: mov di,160*24 + 40*2
mov byte ptr es:[di],'U'
cmp DIRECTION,1
je int9Ret
call isMoveUp
jmp int9Ret
isDown: mov di,160*24 + 40*2
mov byte ptr es:[di],'D'
cmp DIRECTION,0
je int9Ret
call isMoveDown
jmp int9Ret
isLeft: mov di,160*24 + 40*2
mov byte ptr es:[di],'L'
cmp DIRECTION,3
je int9Ret
call isMoveLeft
jmp int9Ret
isRight: mov di,160*24 + 40*2
mov byte ptr es:[di],'R'
cmp DIRECTION,2
je int9Ret
call isMoveRight
jmp int9Ret
;================================================================
isFood: cmp byte ptr es:[si],'9'
jne noFood
call eat_food
call new_food
ret
noFood: mov di,160*24 + 10 *2
mov word ptr es:[di],5535H
call game_over
ret
;================================================================
game_over: call clear_screen
mov ax,4C00H
int 21H
ret
;================================================================
new_food: push ax
push bx
newFood: mov al,0
out 70H,al
in al,71H
mov dl,al ;AL = 0001 0002
shr al,1
shr al,1
shr al,1
shr al,1
and dl,00001111B
mov bl,10
mul bl
add al,dl
mov bl,al
mul bl
shr ax,1
shl ax,1
add ax,168
mov di,ax
cmp byte ptr es:[di],0
jne newFood
push FOOD_COLOR
pop es:[di]
pop bx
pop ax
ret
;================================================================
eat_food: push NEW_NODE
pop ds:[bx+0]
mov bx,OFFSET SNAKE
add bx,NEW_NODE
mov word ptr ds:[bx+0],0 ;0
mov ds:[bx+2],si ;2
push SNAKE_COLOR
pop es:[si]
push SNAKE_HEAD ;4
pop ds:[bx+4]
push NEW_NODE
pop SNAKE_HEAD
add NEW_NODE,6
ret
;================================================================
isMoveRight: mov bx,OFFSET SNAKE
add bx,SNAKE_HEAD
mov si,ds:[bx+2]
add si,2
cmp byte ptr es:[si],0
jne noMoveRight
call new_snake
mov DIRECTION,3
ret
noMoveRight: call isFood
ret
;================================================================
isMoveLeft: mov bx,OFFSET SNAKE
add bx,SNAKE_HEAD
mov si,ds:[bx+2]
sub si,2
cmp byte ptr es:[si],0
jne noMoveLeft
call new_snake
mov DIRECTION,2
ret
noMoveLeft: call isFood
ret
;================================================================
isMoveDown: mov bx,OFFSET SNAKE
add bx,SNAKE_HEAD
mov si,ds:[bx+2]
add si,NEXT_ROW
cmp byte ptr es:[si],0
jne noMoveDown
call new_snake
mov DIRECTION,1
ret
noMoveDown: call isFood
ret
;================================================================
isMoveUp: mov bx,OFFSET SNAKE
add bx,SNAKE_HEAD
mov si,ds:[bx+2]
sub si,NEXT_ROW
cmp byte ptr es:[si],0
jne noMoveUp
call new_snake
mov DIRECTION,0
ret
noMoveUp: call isFood
ret
;================================================================
new_snake: push SNAKE_STERN
pop ds:[bx+0]
mov bx,OFFSET SNAKE
add bx,SNAKE_STERN
push ds:[bx+0]
mov word ptr ds:[bx+0],0
mov di,ds:[bx+2]
push BACK_GROUND_COLOR
pop es:[di]
mov ds:[bx+2],si
push SNAKE_COLOR
pop es:[si]
push SNAKE_HEAD
pop ds:[bx+4]
push SNAKE_STERN
pop SNAKE_HEAD
pop SNAKE_STERN
ret
;================================================================
change_screen_color:
push bx
push cx
push dx
mov bx,0B800H
mov es,bx
mov bx,1
mov cx,2000
changeScreenColor:
inc byte ptr es:[bx]
add bx,2
loop changeScreenColor
pop dx
pop cx
pop bx
ret
;================================================================
init_screen: mov dx,BOUNDARY_COLOR
call init_up_down_line
call init_left_right_line
call init_snake
ret
;================================================================
init_snake: mov bx,OFFSET SNAKE
add bx,SNAKE_HEAD
mov dx,SNAKE_COLOR
mov si,160*10 + 40*2
mov word ptr ds:[bx+0],0
mov ds:[bx+2],si
mov es:[si],dx
mov word ptr ds:[bx+4],6
add bx,6
sub si,2
mov word ptr ds:[bx+0],0
mov ds:[bx+2],si
mov es:[si],dx
mov word ptr ds:[bx+4],12
add bx,6
sub si,2
mov word ptr ds:[bx+0],6
mov ds:[bx+2],si
mov es:[si],dx
mov word ptr ds:[bx+4],18
ret
;================================================================
init_left_right_line:
mov bx,0
mov cx,23
initLeftRightLine:
mov es:[bx],dx
mov es:[bx+158],dx
add bx,NEXT_ROW
loop initLeftRightLine
ret
;================================================================
init_up_down_line:
mov bx,0
mov cx,80
initUpDownLine: mov es:[bx],dx
mov es:[bx+160*23],dx
add bx,2
loop initUpDownLine
ret
;================================================================
clear_screen: mov bx,0
mov dx,0700H
mov cx,2000
clearScreen: mov es:[bx],dx
add bx,2
loop clearScreen
ret
;================================================================
init_reg: mov bx,0B800H
mov es,bx
mov bx,data
mov ds,bx
ret
snake_end: nop
;================================================================
set_new_int9:
mov bx,0
mov es,bx
cli
mov word ptr es:[9*4],OFFSET new_int9 - OFFSET greedy_snake + 7E00H
mov word ptr es:[9*4+2],0
sti
ret
;================================================================
sav_old_int9:
mov bx,0
mov es,bx
push es:[9*4]
pop es:[200H]
push es:[9*4+2]
pop es:[202H]
ret
;================================================================
cpy_greedy_snake:
mov bx,cs
mov ds,bx
mov si,OFFSET greedy_snake
mov bx,0
mov es,bx
mov di,7E00H
mov cx,OFFSET snake_end - OFFSET greedy_snake
cld
rep movsb
ret
code ends
end start
运行效果如下: