8086汇编初学之贪吃蛇

来源:互联网 发布:集团公司网络规划 编辑:程序博客网 时间:2024/05/16 16:22

前言

一直没想过要去学习汇编,觉得需要用汇编的场合无非三种:
1. 与硬件结合很紧密高级语言做不到
2. 时空效率要求甚高算法层面已不能优化到
3. 逆向破解等只能用某些途径看其汇编指令
其余情况下,用汇编无异于有炮不用偏用鸟枪。
本来准备等自己需求以上场合时再去学,但因为学校举办的汇编比赛,计算机学院都要参加,也算是一个由头,于是开始了我的第一个汇编程序。

运行效果

代码只有400行,功能很简略,实现了最基本的游戏流程,看运行效果
这里写图片描述

概述

本质上用汇编去写一个贪吃蛇和用其他语言去实现没什么区别,不过是换一种方式表达,当然,是一种更加麻烦的方式。
以前用c++实现过C++贪吃蛇和C++俄罗斯方块。所以对于这类小游戏,该怎么切是知道了,剩下的事就是找家伙了。

要实现这类简易的小游戏,需要二点:
1. 定时器
2. 非阻塞接收按键
有上面两者便可以搞定一切。
但在汇编下,为这两点,耽搁了不少时间。不对,是三点,还有生成随机数(原本很容易的事都变得麻烦了起来)。

定时器

事实上,查了很多资料,但还是不知道怎样去实现定时器,所以这个需求只能变通的解决。
用空循环来控制时间。

非阻塞接受按键

getInput:    mov al, 0    mov ah, 1    int 16h;查看键盘缓冲区是否有数据    cmp ah, 1;ah为0表示有,否则没有    je getInputEnd    mov al, 0    mov ah, 0    int 16h;从缓冲区读取数据    ;此时值已经在ax里了,做你想做的   getInputEnd:    ret

随机数

    mov ax, 0h;间隔定时器    out 43h, al;通过端口43h    in al, 40h;    in al, 40h;    in al, 40h;访问3次,保证随机性    ;如果对范围并不需要精确,可以直接与运算来获得,    ;否则,用div取余    mov bl, 18    div bl     mov al, ah    mov ah, 0;此时ax的值就是0~18的

代码

assume cs:code,ds:data,ss:stackdata segment    sfood dw 0    sdct dw 0    sbody dw 400 dup(0)data endsstack segment    dw 20 dup(0)stack endscode segmentstart:    mov ax, data    mov ds, ax    mov ax, stack    mov ss, ax    mov sp, 20    mov ax, 0b800h    mov es, ax    mov si, 4 ;保存数据段偏移量    mov cx, 4;初始蛇长度    mov ax, 0A04h    s:;初始化蛇        mov ds:[si], ax        add si, 2        inc al        loop s    mov ax, 4d00h;向右    mov ds:[2], ax;初始化方向    call clearBg;清屏    call outBg;输出地图边框    call outBody;输出蛇    call creatFood;输出食物    mov cx, 30    Game:        push cx        call updateBody        mov cx, 0Fh        aaaa1:            push cx            mov cx, 0FFFh            bbbb:                push cx                call getInput                pop cx                loop bbbb            pop cx            loop aaaa1        ;jmp GameEnd        jmp Game    GameEnd:    ;退出        ;call outBody        mov ax, 4c00h        int 21hupdateBody:    mov ax, ds:[2]    mov di, si    sub di, 2    cmp ax, 4800h    je shang    mov ax, ds:[2]    cmp ax, 5000h    je xia    mov ax, ds:[2]    cmp ax, 4b00h    je zuo    mov ax, ds:[2]    cmp ax, 4d00h    je you    shang:        mov ax, ds:[di]        sub ah, 1        jmp checkBody    xia:        mov ax, ds:[di]        add ah, 1        jmp checkBody    zuo:        mov ax, ds:[di]        sub al, 1        jmp checkBody    you:        mov ax, ds:[di]        add al, 1        ;mov ds:[di], ax        jmp checkBodycheckBody:    push ax    ;判断蛇头是否碰到地图边界    cmp ah, 0    je GameEnd    cmp ah, 20    je GameEnd    cmp al, 0    je GameEnd    cmp al, 20    je GameEnd    ;判断蛇头是否碰到蛇身    mov cx, si    sub cx, 6    mov di, 4    s0:         mov bx, ds:[di]        cmp bx, ax        je GameEnd        add di, 2        sub cx, 1        loop s0    pop ax    ;判断蛇头是否吃到食物    mov bx, ds:[0]    cmp ax, bx    je addBody    jmp updateStartupdateStart:    mov cx, si    sub cx, 6    mov di, 4    push ax    mov dl, ' ';字符    mov dh, 0;颜色    mov bx, ds:[di]    call outStr    s5:         mov dx, ds:[di+2]        mov ds:[di], dx        add di, 2        sub cx, 1        loop s5    mov dl, ' ';字符    mov dh, 71h;颜色    mov bx, ds:[di]    call outStr    pop ax    mov ds:[di], ax    mov dl, ' ';字符    mov dh, 44h;颜色    mov bx, ds:[di]    call outStrupdateEnd:    retaddBody:    mov dl, ' ';字符    mov dh, 71h;颜色    mov bx, ds:[di]    call outStr    mov ax, ds:[0]    mov ds:[si], ax    mov dl, ' ';字符    mov dh, 44h;颜色    mov bx, ds:[si]    call outStr    add si, 2    call creatFood    jmp updateEndgetInput:;获取键盘输入    mov al, 0    mov ah, 1    int 16h;接收键盘    cmp ah, 1    je getInputEnd    mov al, 0    mov ah, 0    int 16h;    mov cx, ax;键盘值在ax    ;判断输入    cmp cx, 4800h    je gshang    cmp cx, 5000h    je gxia    cmp cx, 4b00h    je gzuo    cmp cx, 4d00h    je gyou    jmp getInputEnd    gshang:        mov ax, ds:[2]        cmp ax, 5000h        je getInputEnd        jmp fx    gxia:        mov ax, ds:[2]        cmp ax, 4800h        je getInputEnd        jmp fx    gzuo:        mov ax, ds:[2]        cmp ax, 4d00h        je getInputEnd        jmp fx    gyou:        mov ax, ds:[2]        cmp ax, 4b00h        je getInputEnd        jmp fx    fx:;更改方向标志        mov ds:[2], cx    getInputEnd:        ret;结束outBody:    mov cx, si    sub cx, 6    mov di, 4    s1:         mov ax, ds:[di]        mov dl, ' ';字符        mov dh, 71h;颜色        mov bl, al;列        mov bh, ah;行        call outStr        add di, 2        sub cx, 1        loop s1    mov dl, ' '    mov dh, 44h    mov ax, ds:[di]    mov bl, al    mov bh, ah    call outStr    retoutBg:    mov dl, ' ';字符    mov dh, 71h;颜色    mov bl, 0;列    mov bh, 0;行    mov cx, 20    row:        push cx        push bx        call outStr;上边界        pop bx        push bx        add bh, 20        call outStr;下边界        pop bx        inc bl;列加1        pop cx        loop row    mov bl, 0;    mov bh, 0;    mov cx, 21    col:        push cx        push bx        call outStr;左边界        pop bx        push bx        add bl, 20        call outStr;右边界        pop bx        inc bh;行加1        pop cx        loop col    retoutStr: ;在指定位置输出字符    mov al, 80    mul bh;行乘以80    mov bh, 0    add bl, bl;    add ax, bx;加上列即为偏移量    push si    mov si, ax    add si, si    mov es:[si], dl    mov es:[si+1], dh    mov es:[si+2], dl    mov es:[si+3], dh    pop si    retcreatFood:;生成食物    call getFoodPosition    mov dl, ' '    mov dh, 071h    mov bx, ds:[0]    call outStr    retgetFoodPosition:;获取食物位置    f1:         call getRand        mov ds:[0], al        call getRand        mov ds:[1], al        mov cx, si        sub cx, 4        mov di, 4        s11:             mov ax, ds:[di]            cmp ax, ds:[0]            je f1            add di, 2            sub cx, 1            loop s11    retgetRand:;获取随机数 范围1~19    mov ax, 0h;间隔定时器    out 43h, al;通过端口43h    in al, 40h;    in al, 40h;    in al, 40h;访问3次,保证随机性    mov bl, 18    div bl     mov al, ah    mov ah, 0    inc al    retclearBg:    ;清屏    mov ax, 3h    int 10h    retcode endsend start
1 0
原创粉丝点击