吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5934|回复: 34
收起左侧

[其他原创] 【汇编】 用汇编写了个贪吃蛇

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

代码已上传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

免费评分

参与人数 23吾爱币 +28 热心值 +20 收起 理由
萝莉兔女郎 + 1 + 1 用心讨论,共获提升!
gentledream + 1 + 1 热心回复!
ntluking + 1 膜拜汇编大佬
c03xp + 1 + 1 我很赞同!
onlylonely + 1 + 1 大神。
飞鲲之梦 + 1 + 1 我很赞同!
Key君 + 2 + 1 手搓汇编可太厉害了
Anekys + 1 + 1 膜拜大佬,汇编手搓贪吃蛇
w92vv + 1 + 1 厉害了!
笙若 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
9695 + 1 + 1 牛了,学习了
wushaominkk + 5 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Loser_Lus + 1 真 NB
luanshils + 2 + 1 🐮
baronL + 1 + 1 热心回复!
你爷爷的爷爷 + 1 + 1 牛逼
fghqa3v + 1 + 1 用心讨论,共获提升!
乎乎 + 1 + 1 牛逼克拉斯
minchang + 1 + 1 热心回复!
KSTG_茶飘香 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
我乃小明 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
绫织梦 + 1 太强了
TSIR + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| iTruth 发表于 2020-3-6 11:48
此用户无法显示 发表于 2020-3-6 10:21
!!!还能手撸汇编写游戏!!!想知道要能够破解程序要达到怎样的水平,而且看网上这方面教程少得可怜,楼 ...

这要看你要破的是啥程序了,一些比较简单的你只要稍微有点汇编基础,还会点OD的常用操作就没问题了。一些保护的比较厉害的程序就难说了。论坛里应该有这方面的视频教程,你能吃透的话大多数程序应该是没问题的
 楼主| iTruth 发表于 2020-3-3 20:26
longsui48 发表于 2020-3-3 19:33
大佬 有没有好的汇编知道 最近想学这方面的东西

我当初的入门书个人感觉不适合新手,我的第一个汇编程序是跑在MBR上的。。
即便如此我还是告诉你我的入门书吧,《x86 汇编语言:从实模式到保护模式 》
入门之后最好学着看intel的白皮书,上面有任何你想知道的
我乃小明 发表于 2020-3-3 17:51
殊_途 发表于 2020-3-3 17:52
厉害了老哥
随缘命运 发表于 2020-3-3 17:57
学习了,楼主,赞一个
头像被屏蔽
那年听风 发表于 2020-3-3 17:59
提示: 作者被禁止或删除 内容自动屏蔽
plattl 发表于 2020-3-3 18:09
厉害,学习到东西了。
cheng32375 发表于 2020-3-3 18:09
大佬牛批,太厉害了
semiuel 发表于 2020-3-3 18:11
不明觉厉,请允许我把大佬的照片挂起来膜拜。
bjxiaoyao 发表于 2020-3-3 18:19
善哉善哉,老衲要给楼主三十二个赞!
mumu324 发表于 2020-3-3 18:30
楼主,厉害啊,我也学过汇编写程序,不简单啊
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 23:50

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表