最新公告
  • 欢迎您光临小酒资源吧,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入我们
  • 【汇编】 用汇编写了个贪吃蛇

    【汇编】 用汇编写了个贪吃蛇 最后编辑:2020-09-01
    增值服务: 自动发货 使用说明 安装指导 环境配置二次开发BUG修复

    前言
    软件的逆向分析和破解需要扎实的汇编基础,为了提高自己的汇编水平所以用汇编写了个贪吃蛇.
    这份代码也能给有类似想法的人提供一个参考
    对于我的代码有任何意见或建议请务必提出来

    代码已上传github,但不知道这是否符合版规就不放链接了

    pic.jpg

    实现细节

    我代码里除了main函数外所有的函数都遵循了stdcall的调用约定,个人认为这种调用约定比cdecl要方便很多.简直就是为了汇编而生的调用约定
    蛇本身使用了一个双向链表,每个表项都描述了当前块的坐标,上一个和下一个块的首地址,布局是:
    DWORD X

    DWORD Y
    DWORD next
    DWORD prev

    编译
    用nasm编译然后用gcc链接
    链接方式不唯一,不一定必须要用gcc来链接但nasm是必要的

    nasm -f win32 Retro_Snaker.asm -o Retro_Snaker.o
    gcc Retro_Snaker.o -o Retro_Snaker.exe

    代码:
    [Asm] 纯文本查看 复制代码extern _printf
    extern _kbhit
    extern _getch
    extern _putchar
    extern _malloc
    extern _free
    extern _time
    extern _srand
    extern _rand
    extern _exit
    extern _GetStdHandle@4
    extern _SetConsoleCursorPosition@8
    extern _SetConsoleCursorInfo@8
    extern _MessageBoxA@16
    extern _Sleep@4

    segment .data
    pszNewLine db 0x0D, 0x0A, 0
    pszScore db "Score: %d", 0
    pszTarget db "Target: %d", 0
    pszTitle db "Snake", 0
    pszFailed db "You lost", 0
    pszWon db "You win", 0

    segment .bss
    AreaX equ 70
    AreaY equ 24
    UP equ 0
    DOWN equ 1
    LEFT equ 2
    RIGHT equ 3
    Target equ 100
    pszMapbuffer resb AreaX+1
    pxySnakeHead resd 1
    pxySnakeTail resd 1
    nSnakeLenth resd 1
    nxySnakeFoodX resd 1
    nxySnakeFoodY resd 1
    uniCurDir resw 1 ;0->上; 1->下; 2->左; 3->右

    segment .text
    global _main

    ;添加蛇头部
    ;参数: word x
    ; word y
    _add_snake_head@8:
    push ebp
    mov ebp, esp
    sub esp, 4
    mov dword [esp], 16
    call _malloc
    mov edx, [ebp+8]
    mov dword [eax], edx ;x
    mov edx, [ebp+12]
    mov dword [eax+4], edx ;y
    mov edx, [pxySnakeHead]
    mov dword [edx+12], eax ;prev
    mov dword [eax+8], edx ;next
    mov dword [eax+12], eax ;prev->prev
    mov dword [pxySnakeHead], eax ;更新蛇头位置
    push \’*\’
    push dword [eax+4]
    push dword [eax]
    call _printchar@12
    leave
    ret 8

    ;添加蛇尾部
    ;参数: dword x
    ; dword y
    _add_snake_tail@8:
    push ebp
    mov ebp, esp
    sub esp, 4
    mov dword [esp], 16
    call _malloc
    mov edx, [ebp+8]
    mov dword [eax], edx ;x
    mov edx, [ebp+12]
    mov dword [eax+4], edx ;y
    mov dword [eax+8], 0 ;next
    mov ebx, [pxySnakeTail]
    mov dword [eax+12], ebx ;prev
    mov dword [ebx+8], eax ;prev->next = eax
    mov dword [pxySnakeTail], eax
    push \’*\’
    push dword [eax+4]
    push dword [eax]
    call _printchar@12
    leave
    ret 8

    ;按情况去掉蛇尾
    _remove_snake_tail@0:
    push ebp
    mov ebp, esp
    ;开始比较蛇尾和蛇尾的上一节的x和y是否相等
    ;这将决定是否在屏幕上擦除蛇尾
    xor cx, cx
    mov eax, [pxySnakeTail] ;蛇尾首地址
    mov ebx, [eax+12] ;蛇尾上一节的首地址
    mov edx, [ebx] ;edx = tail->x
    cmp [eax], edx
    setne cl
    mov edx, [ebx+4]
    cmp [eax+4], edx
    setne ch
    cmp bx, 0
    jz LRemoveTail
    push \’ \’
    push dword [eax+4]
    push dword [eax]
    call _printchar@12
    LRemoveTail:
    mov eax, [pxySnakeTail] ;eax = tail
    mov ebx, [eax+12] ;ebx = tail->prev
    mov dword [pxySnakeTail], ebx ;tail = ebx
    mov dword [ebx+8], 0 ;ebx->next=0
    push eax
    call _free
    add esp, 4
    leave
    ret 0

    ;初始化蛇
    _init_snake@0:
    push ebp
    mov ebp, esp
    sub esp, 4
    mov word [uniCurDir], RIGHT ;初始方向向右
    mov dword [nSnakeLenth], 3 ;蛇长度初始为3
    ;开始初始化蛇头
    mov dword [esp], 16
    call _malloc
    mov dword [pxySnakeHead], eax
    mov dword [pxySnakeTail], eax
    mov dword [eax], 5 ;x
    mov dword [eax+4], 1 ;y
    mov dword [eax+8], 0 ;next
    mov dword [eax+12], eax ;prev
    ;打印蛇头
    push \’*\’
    push 1
    push 5
    call _printchar@12
    ;添加蛇身
    mov ecx, [nSnakeLenth]
    dec ecx
    LInitPrintSnake:
    push ecx
    push 1
    mov eax, ecx
    add eax, 2
    push eax
    call _add_snake_tail@8
    pop ecx
    loop LInitPrintSnake
    leave
    ret 0

    ;检测指定坐标是否在蛇身内
    ;参数: dword x
    ; dword y
    ; dword isCheckHead
    _is_pos_in_snake@12:
    push ebp
    mov ebp, esp
    mov eax, [pxySnakeHead]
    cmp dword [ebp+16], 0 ;是否跳过头部检测
    je LCheck
    mov eax, [eax+8]
    LCheck:
    xor cx, cx
    mov edx, dword [ebp+8]
    cmp [eax], edx
    setne cl
    mov edx, dword [ebp+12]
    cmp [eax+4], edx
    setne ch
    cmp cx, 0
    je LInBody
    cmp dword [eax+8], 0
    je LNotInBody
    mov eax, [eax+8]
    jmp LCheck
    LNotInBody:
    mov eax, 0
    jmp LIsPosInSnakeEnd
    LInBody:
    mov eax, 1
    LIsPosInSnakeEnd:
    leave
    ret 12

    ;检测是否吃到了食物并决定是否增长蛇
    _check_food@0:
    push ebp
    mov ebp, esp
    xor dx, dx
    mov eax, [pxySnakeHead]
    mov bx, [eax]
    cmp bx, [nxySnakeFoodX]
    setne dl
    mov bx, [eax+4]
    cmp bx, [nxySnakeFoodY]
    setne dh
    cmp dx, 0
    jne LCheckFoodEnd
    inc dword [nSnakeLenth]
    call _gen_food@0
    mov eax, [pxySnakeTail]
    push dword [eax+4]
    push dword [eax]
    call _add_snake_tail@8
    LCheckFoodEnd:
    leave
    ret 0

    ;检测是否赢了
    _check_won@0:
    push ebp
    mov ebp, esp
    mov eax, dword [nSnakeLenth]
    sub eax, 3
    cmp eax, Target
    jl LFailCheckEnd
    call _free_all@0
    push 0
    push pszTitle
    push pszWon
    push 0
    call _MessageBoxA@16
    mov dword [esp], 0
    call _exit
    LCheckWonEnd:
    leave
    ret 0

    ;检测是否已经输了
    _check_failed@0:
    push ebp
    mov ebp, esp
    sub esp, 4
    mov edx, [pxySnakeHead]
    ;检测蛇头是否碰到了蛇身
    push 1 ;跳过头部检测
    push dword [edx+4]
    push dword [edx]
    call _is_pos_in_snake@12
    cmp eax, 0
    je LCheckXZ
    jmp LFailed
    ;下面检测是否碰壁
    LCheckXZ:
    mov edx, [pxySnakeHead]
    cmp dword [edx], -1
    jne LCheckYZ
    jmp LFailed
    LCheckYZ:
    cmp dword [edx+4], -1
    jne LCheckXE
    jmp LFailed
    LCheckXE:
    cmp dword [edx], AreaX-2
    jne LCheckYE
    jmp LFailed
    LCheckYE:
    cmp dword [edx+4], AreaY-2
    jne LFailCheckEnd
    jmp LFailed
    ;下面处理输了的情况
    LFailed:
    call _free_all@0
    push 0
    push pszTitle
    push pszFailed
    push 0
    call _MessageBoxA@16
    mov dword [esp], 0
    call _exit
    LFailCheckEnd:
    leave
    ret 0

    ;根据按键改变蛇的方向
    _get_new_dir@0:
    push ebp
    mov ebp, esp
    call _kbhit
    cmp eax, 0
    je LGetNewDirEnd
    call _getch
    cmp eax, \’w\’
    jne LK_A
    cmp word [uniCurDir], DOWN
    je LGetNewDirEnd ;防止蛇直接掉头
    mov word [uniCurDir], UP
    jmp LGetNewDirEnd
    LK_A:
    cmp eax, \’a\’
    jne LK_S
    cmp word [uniCurDir], RIGHT
    je LGetNewDirEnd
    mov word [uniCurDir], LEFT
    jmp LGetNewDirEnd
    LK_S:
    cmp eax, \’s\’
    jne LK_D
    cmp word [uniCurDir], UP
    je LGetNewDirEnd
    mov word [uniCurDir], DOWN
    jmp LGetNewDirEnd
    LK_D:
    cmp eax, \’d\’
    jne LGetNewDirEnd
    cmp word [uniCurDir], LEFT
    je LGetNewDirEnd
    mov word [uniCurDir], RIGHT
    LGetNewDirEnd:
    leave
    ret 0

    ;使蛇移动一步
    _move_snake@0:
    push ebp
    mov ebp, esp
    sub esp, 8
    ;保存当前蛇头坐标
    mov eax, [pxySnakeHead]
    mov ebx, [eax]
    mov dword [esp], ebx ;x
    mov ebx, [eax+4]
    mov dword [esp+4], ebx ;y
    mov eax, [pxySnakeHead]
    cmp word [uniCurDir], UP
    je LUP
    cmp word [uniCurDir], DOWN
    je LDOWN
    cmp word [uniCurDir], LEFT
    je LLEFT
    cmp word [uniCurDir], RIGHT
    je LRIGHT
    jmp LDIREND
    LUP:
    dec dword [esp+4]
    jmp LDIREND
    LDOWN:
    inc dword [esp+4]
    jmp LDIREND
    LLEFT:
    dec dword [esp]
    jmp LDIREND
    LRIGHT:
    inc dword [esp]
    LDIREND:
    call _add_snake_head@8
    call _remove_snake_tail@0
    leave
    ret 0

    ;生成食物
    _gen_food@0:
    push ebp
    mov ebp, esp
    cmp dword [nSnakeLenth], (AreaX-2)*(AreaY-2)
    jge LGenFoodEnd
    LGenFood:
    push 0
    xor edx, edx
    call _rand
    mov ebx, AreaY-3
    div ebx
    mov dword [nxySnakeFoodY], edx
    push edx
    xor edx, edx
    call _rand
    mov ebx, AreaX-3
    div ebx
    mov dword [nxySnakeFoodX], edx
    push edx
    call _is_pos_in_snake@12
    cmp eax, 0
    jne LGenFood
    push \’#\’
    push dword [nxySnakeFoodY]
    push dword [nxySnakeFoodX]
    call _printchar@12
    call _print_score@0
    LGenFoodEnd:
    leave
    ret 0

    ;基于窗口原点移动光标
    ;参数: byte x
    ; byte y
    _gotoxy@4:
    push ebp
    mov ebp, esp
    push word [ebp+8]
    push word [ebp+10]
    push -11
    call _GetStdHandle@4
    push eax
    call _SetConsoleCursorPosition@8
    leave
    ret 4

    ;基于地图原点移动光标
    ;参数: word x
    ; word y
    _map_gotoxy@8:
    push ebp
    mov ebp, esp
    sub esp, 4
    and dword [esp], 0
    mov al, byte [ebp+8]
    inc al
    mov byte [esp], al
    mov al, byte [ebp+12]
    inc al
    mov byte [esp+2], al
    call _gotoxy@4
    leave
    ret 8

    ;基于地图原点打印一个字符
    ;参数: dword x
    ; dword y
    ; dword char
    _printchar@12:
    push ebp
    mov ebp, esp
    sub esp, 4
    push dword [ebp+8]
    push dword [ebp+12]
    call _map_gotoxy@8
    mov eax, [ebp+16]
    mov [esp], eax
    call _putchar
    leave
    ret 12

    ;打印地图
    _printmap@0:
    push ebp
    mov ebp, esp
    sub esp, 8
    ;定位光标到(0,0)处
    push 0
    call _gotoxy@4
    mov ecx, AreaY
    LLines:
    push ecx
    mov ecx, AreaX
    ;根据行的位置决定打印什么
    cmp dword [esp], 1
    je LHeaderLine
    cmp dword [esp], AreaY
    je LHeaderLine
    mov byte [esp+4], \’|\’
    mov byte [esp+5], \’ \’
    jmp LPrintLine
    LHeaderLine:
    mov byte [esp+4], \’+\’
    mov byte [esp+5], \’-\’
    ;构建一行
    LPrintLine:
    mov al, [esp+4]
    mov byte [pszMapbuffer], al
    mov ecx, AreaX-2
    LCenter:
    mov al, byte [esp+5]
    mov byte [pszMapbuffer+ecx], al
    loop LCenter
    mov al, byte [esp+4]
    mov byte [pszMapbuffer+AreaX-1], al
    ;打印构建好的行
    push pszMapbuffer
    call _printf
    add esp, 4
    ;行末尾打印换行
    LineEnd:
    push pszNewLine
    call _printf
    add esp, 4
    pop ecx
    dec ecx
    jnz LLines
    leave
    ret 0

    ;打印分数
    _print_score@0:
    push ebp
    mov ebp, esp
    sub esp, 8
    push word AreaX-12
    push word AreaY
    call _gotoxy@4
    mov eax, [nSnakeLenth]
    sub eax, 3
    mov dword [esp+4], eax
    mov dword [esp], pszScore
    call _printf
    push word AreaX-12
    push word AreaY+1
    call _gotoxy@4
    mov dword [esp+4], Target
    mov dword [esp], pszTarget
    call _printf
    leave
    ret 0

    ;释放整条蛇,用于游戏结束后的资源释放
    _free_all@0:
    push ebp
    mov ebp, esp
    sub esp, 4
    mov ebx, [pxySnakeHead]
    LFreeAll:
    mov eax, ebx
    mov ebx, [ebx+8]
    mov dword [esp], eax
    call _free
    cmp ebx, 0
    je LGenFoodEnd
    jmp LFreeAll
    LFreeAllEnd:
    leave
    ret 0

    _main:
    push ebp
    mov ebp, esp
    sub esp, 32
    ;隐藏光标
    mov dword [esp], 1
    mov dword [esp+4], 0
    lea eax, [esp]
    push eax
    push -11
    call _GetStdHandle@4
    push eax
    call _SetConsoleCursorInfo@8
    ;更新随机数种子
    mov dword [esp], 0
    call _time
    mov dword [esp], eax
    call _srand
    ;初始化
    call _printmap@0
    call _init_snake@0
    call _gen_food@0
    ;游戏主循环
    LGameMainLoop:
    call _get_new_dir@0
    call _move_snake@0
    call _check_food@0
    call _check_won@0
    call _check_failed@0
    push 100
    call _Sleep@4
    jmp LGameMainLoop
    leave
    ret

    猜你在找

    1. 本站所有资源来源于用户上传和网络,因此不包含技术服务请大家谅解!如有侵权请邮件联系客服!603313839@qq.com
    2. 本站不保证所提供下载的资源的准确性、安全性和完整性,资源仅供下载学习之用!如有链接无法下载、失效或广告,请联系客服处理,有奖励!
    3. 您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容资源!如用于商业或者非法用途,与本站无关,一切后果请用户自负!
    4. 如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!

    小酒资源吧 » 【汇编】 用汇编写了个贪吃蛇

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    小酒资源吧
    一个高级程序员模板开发平台
    • 2020-09-01Hi,初次和大家见面了,请多关照!

    Hi, 如果你对这款模板有疑问,可以跟我联系哦!

    联系客服
    • 2248会员总数(位)
    • 4394资源总数(个)
    • 9本周发布(个)
    • 0 今日发布(个)
    • 338稳定运行(天)

    提供最优质的资源集合

    立即查看 了解详情
  • 2020 XiaoJiu8.cn - & WordPress Theme. All rights reserved 黔ICP备17003460号-5

  • XML地图 | 站长导航
         
    升级SVIP尊享更多特权立即升级