⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snake.asm

📁 ELFkickers是一组elf工具
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;; snake.asm: Copyright (C) 2001 by Brian Raiter, under the GNU;; General Public License. No warranty.;;;; To build:;;	nasm -f bin -o snake snake.asm && chmod +x snake;;;; Use 4, n, or the left-arrow key to turn the snake left.;; Use 5, m, or the right-arrow key to turn the snake right.;; Eating the blocks adds to your score and makes you grow longer.;; Avoid the walls and your own tail.;;;; Note that this program assumes that it is running on a terminal;; that has the VT100 line-drawing characters as the alternate;; character set. If you're playing on a Linux console and you see a;; bunch of lowercase letters instead of lines, try typing "echo -e;; '\e(B\e)0'" before starting the game. If that doesn't help, or if;; instead you see a jumble of non-ASCII characters, you may need to;; switch to a console font with the full VT100 character set in order;; to play.BITS 32;; Macros for accessing addresses in .text and .bss via ebp.%define	DATAOFF(addr)		byte ebp + ((addr) - score);; The system calls used by this program.%define	SC_exit			1	; exit(bl)%define	SC_read			3	; eax = read(ebx, ecx, edx)%define	SC_write		4	; eax = write(ebx, ecx, edx)%define SC_pause		29	; eax = pause()%define SC_ioctl		54	; eax = ioctl(ebx, ecx, edx)%define SC_sigaction		67	; eax = sigaction(ebx, ecx, edx)%define SC_gettimeofday		78	; eax = gettimeofday(ebx, ecx)%define SC_setitimer		104	; eax = setitimer(ebx, ecx, edx)%define SC_select		142	; eax = select(ebx, ecx, edx, esi, edi);; ioctl values%define TCGETS			0x5401%define TCSETS			0x5402%define ICANON			0000002%define ECHO			0000010;; signal values%define	SIGALRM			14;; ASCII character names%define	NL			012q%define	FF			014q%define	SO			016q%define	SI			017q%define	ESC			033q%define	CSI			233q;; How the program tracks directions. (These values are also ORed;; together to indicate the various VT-100 line-drawing characters.)%define	NORTH			1%define	EAST			2%define	SOUTH			4%define	WEST			8;; Dimensions of the screen and the playing area.%define WIDTH			78%define	HEIGHT			24%define	CENTERPOINT		((HEIGHT - 1) / 2) * WIDTH + (WIDTH - 1) / 2%define	RIGHTCOL		'79'%define	BOTTOMROW		'24';; The number of turns it takes for the food to decay.%define	FOOD_HALFLIFE		42;; Indices for messages to the user.%define	helpmsgcode		51%define	endmsgcode		91%define	filledmsgcode		101%define	ouromsgcode		135%define	philosmsgcode		172%define	poetrymsgcode		209%define	origin			0x08048000;; The ELF header and program segment table.		org	originehdr:						; Elf32_Ehdr		db	0x7F, "ELF", 1, 1, 1	;   e_ident	times 9	db	0		dw	2			;   e_type		dw	3			;   e_machine		dd	1			;   e_version		dd	_start			;   e_entry		dd	phdr - $$		;   e_phoff		dd	0			;   e_shoff		dd	0			;   e_flags		dw	ehdrsize		;   e_ehsize		dw	phdrsize		;   e_phentsizephdr:								; Elf32_Phdr		dw	1			;   e_phnum	;   p_type		dw	0			;   e_shentsize		dw	0			;   e_shnum	;   p_offset		dw	0			;   e_shstrndxehdrsize	equ	$ - ehdr		dd	$$					;   p_vaddr		dd	$$					;   p_paddr		dd	filesz					;   p_filesz		dd	memsz					;   p_memsz		dd	7					;   p_flags		dd	0x1000					;   p_alignphdrsize	equ	$ - phdr;; getkey retrieves a single character from standard input if one is;; waiting to be read.;;;; input:;; ecx = pointer to a byte in memory at which to store the character.;;;; output:;; al = the contents of [ecx].;; [ecx] = the character input, or zero if no character was available,;;         or 'q' if standard input could not be read.;; eax, ebx, and edx are altered.getkey:;; Call select, waiting on the first file descriptor only, and setting;; the time to wait to zero. If select returns an error, return 'q' to;; the caller. If select returns zero, return zero to the caller.;; Otherwise, call read.		xor	eax, eax		xor	ebx, ebx		cdq		mov	[ecx], al		pusha		inc	ebx		mov	ecx, fdset		mov	[ecx], ebx		xor	esi, esi		lea	edi, [DATAOFF(timer)]		mov	[edi], eax		mov	[byte edi + 4], eax		mov	al, 142		int	0x80		dec	eax		popa		jl	.return		js	.retquit		mov	al, SC_read		inc	edx		int	0x80;; If read returned zero (i.e., EOF) or an error, return 'q' to the;; caller. Otherwise, return the retrieved character.		dec	eax		jz	.return.retquit:	mov	byte [ecx], 'q'.return:	mov	al, [ecx]		ret;; zmove appends a cursor-positioning VT-100 escape sequence to the;; given buffer.;;;; input:;; eax = the zero-based coordinates to move the cursor to, in the form;;       y * WIDTH + x.;; edi = the buffer to write the escape sequence to.;;;; output:;; edi = the position following the escape sequence.;; eax and edx are altered.zmove:		mov	dl, WIDTH		div	dl		push	eax		inc	eax		aam		bswap	eax		add	eax, ESC | ('[00' << 8)		stosd		pop	eax		mov	al, ah		inc	eax		aam		bswap	eax		shr	eax, 8		add	eax, ';00H'		stosd		ret;; addvtchar appends a VT-100 cursor-position escape sequence followed;; by a line-drawing character to the given buffer.;;;; eax = the zero-based coordinates to move the cursor to.;; dl  = the line-drawing character, given as a combination of;;	 direction bit flags.;; edi = the buffer to write the escape sequence to.;;;; output:;; edi = the position following the line-drawing character.;; eax, ebx, and edx are altered.addvtchar:		push	edx		mov	[DATAOFF(scr) + eax], dl		call	zmove		pop	eax		mov	edx, eax		lea	ebx, [DATAOFF(vtlines)]		xlatb		stosb		ret;; refresh writes the contents of outbuf to standard output.;;;; input:;; edi = one past the last character in outbuf to write.;;;; output:;; edi = outbuf.;; eax, ebx, ecx, and edx are altered.refresh:		mov	eax, ESC | ('[' << 8) | (BOTTOMROW << 16)		stosd		mov	eax, ';0H' | (SI << 24)		stosd		mov	edx, edi		mov	edi, outbuf		mov	ecx, edi		sub	edx, ecx		xor	ebx, ebx		lea	eax, [byte ebx + SC_write]		inc	ebx		int	0x80tick:		ret;; The program begins here._start:;; ebp is set to point to an address near the top of the .bss;; section. It will retain this value throughout the program.		mov	ebp, score;; The attributes of the tty connected to standard input are;; retrieved, and then canonical-mode and input-echoing are turned;; off. This puts the terminal in a mode similar to what ncurses calls;; cbreak mode. The original attributes are remembered so that they;; can be restored at the end.		lea	edx, [DATAOFF(termios)]		mov	ecx, TCGETS		xor	ebx, ebx		lea	eax, [byte ebx + SC_ioctl]		int	0x80		mov	eax, [DATAOFF(termios.lflag)]		push	eax		and	eax, byte ~(ICANON | ECHO)		mov	[DATAOFF(termios.lflag)], eax		inc	ecx		lea	eax, [byte ebx + SC_ioctl]		int	0x80		pop	dword [DATAOFF(termios.lflag)];; A do-nothing signal hander is installed for SIGALRM, and then an;; interval timer is set up to go off every 0.2 seconds.		lea	eax, [byte ebx + SC_sigaction]		cdq		mov	bl, SIGALRM		lea	ecx, [DATAOFF(sigact)]		int	0x80		lea	ecx, [DATAOFF(timer)]		mov	eax, 200 * 1000		mov	[byte ecx + 4], eax		mov	[byte ecx + 12], eax		cdq		xor	ebx, ebx		lea	eax, [byte ebx + SC_setitimer]		int	0x80;; The scr buffer is initialized by adding the outer walls of the;; playing field.		lea	edi, [DATAOFF(scr)]		mov	al, SOUTH | EAST		stosb		mov	al, EAST | WEST		push	byte WIDTH - 2		pop	ecx		rep stosb		mov	al, SOUTH | WEST		stosb		mov	esi, edi		mov	al, NORTH | SOUTH		stosb		add	edi, byte WIDTH - 2		stosb		mov	cl, ((HEIGHT - 3) * WIDTH) & 0xFF		mov	ch, ((HEIGHT - 3) * WIDTH) >> 8		rep movsb		mov	al, NORTH | EAST		stosb		mov	al, EAST | WEST		mov	cl, WIDTH - 2		rep stosb		mov	byte [edi], NORTH | WEST;; edi is initialized to point to the output buffer. It will continue;; to point into this buffer for the rest of the program.		mov	edi, outbuf;; The snake is set to begin in the middle of the playing field, and;; is set to extend by one unit. A food block is placed there as well,;; but having already expired so that the program will create a new;; food block on the first iteration of the main loop.		mov	eax, CENTERPOINT		mov	[snake], eax		mov	byte [DATAOFF(scr) + eax], EAST | WEST		mov	[DATAOFF(foodpos)], eax;; The current time is used to initialize our pseduorandom-number;; generator, and is also used to select between EAST and WEST as the;; snake's starting direction of movement. A Ctrl-L keystroke is;; inserted into the input queue, so that the program will redraw;; everything on the first iteration of the main loop.		lea	ebx, [DATAOFF(rndseed)]		lea	eax, [byte ecx + SC_gettimeofday]		int	0x80		add	eax, [ebx]		mov	al, WEST		jp	.gowest		mov	al, EAST.gowest:	mov	[DATAOFF(dir)], al		mov	byte [DATAOFF(key + 1)], FF;; The main loop, where the program will remain until the game ends.mainloop:;; Examine the input queue. If a keystroke is waiting in there, then;; remove it and use it as this iteration's keystroke. (If two;; keystrokes are waiting there, remove the first one and move the;; second one into its position.)		lea	ecx, [DATAOFF(key)]		mov	al, [byte ecx + 1]		or	al, al		jz	.readkey		xor	edx, edx		cmp	dl, [byte ecx + 2]		jz	.retlast		xchg	dl, [byte ecx + 2].retlast:	mov	[byte ecx + 1], dl.retkey:	mov	[ecx], al		jmp	short .endkeys;; Otherwise, check for an incoming character. If anything besides ESC;; is returned (including zero, indicating no keys have been pressed),;; then proceed with that key. Otherwise, check for a second;; character. If anything besides '[' or 'O' is returned, then put the;; character in the input queue and proceed with the ESC. Otherwise,;; check for a third character. If anything besides 'C' or 'D' is;; returned, then put it and the previous character into the input;; queue and proceed with the ESC. Otherwise, replace the arrow-key;; sequence with an 'm' or an 'n', as appropriate..readkey:	call	getkey		cmp	al, ESC		jnz	.endkeys		inc	ecx		call	getkey		cmp	al, '['		jz	.getthird		cmp	al, 'O'		jnz	.endkeys.getthird:	inc	ecx		call	getkey		cmp	al, 'C'		jz	.acceptarrow		cmp	al, 'D'		jnz	.endkeys.acceptarrow:	add	al, 'm' - 'C'		movzx	eax, al		mov	[byte ecx - 2], eax.endkeys:;; If a 'q' was retrieved, exit the program at once. If a Ctrl-L was;; retrieved, then redraw the screen.		cmp	al, 'q'		jz	near leavegame		cmp	al, FF		jnz	.continue;; The screen is erased, and the VT-100 line-drawing character set is;; selected. The scr array is read, and each element is translated;; into one of the line-drawing characters and output, with a newline;; inserted at the end of each row. Finally, the normal character set;; is re-selected, and the program jumps to the routine to display the;; current score.		mov	eax, ESC | ('[H' << 8) | (ESC << 24)		stosd		mov	eax, '[J' | (SO << 16) | (SO << 24)		stosd		lea	esi, [DATAOFF(scr)]		lea	ebx, [DATAOFF(vtlines)]		push	byte HEIGHT		pop	ecx.initoutloop:	mov	ch, WIDTH.lineoutloop:	lodsb		xlatb		stosb		dec	ch		jnz	.lineoutloop		dec	ecx		jz	.outloopend		mov	al, 10		stosb		jmp	short .initoutloop.outloopend:	mov	al, SI

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -