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

📄 ls.asm

📁 ELFkickers是一组elf工具
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;; ls.asm: Copyright (C) 2001 by Brian Raiter <breadbox@muppetlabs.com>,;; under the GNU General Public License. No warranty. See COPYING.;;;; To build:;;	nasm -f bin -o ls ls.asm && chmod +x ls;;;; Usage: ls [-abdilsBCFNR1] [--] [FILE]...;; -C  columnar output; default if stdout is a tty;; -1  one file per output line; default if stdout is not a tty;; -l  "long" output;; -F  show file type suffixes;; -i  show inode numbers;; -s  show size of files in 1K-blocks;; -d  don't expand directories;; -a  show all (hidden) files;; -B  don't show files ending in ~ (backups);; -N  don't replace non-graphic characters with a question mark;; -b  show non-graphic characters as octal escape sequences;; -R  recursively list contents of subdirectories;;;; Differences from GNU ls:;; * Columnar output isn't very intelligent. (Real columns would;;   require loading the entire directory contents before displaying.);; * There are no sorting options. (Ditto previous obstacle.);; * There is no option to print uid/gid by name. (This would require;;   reading and parsing the appropriate /etc files.);; * Showing the file's modification age is less useful than the;;   modification time. (This would require reading /etc/localtime to;;   get the proper offset from UTC.)BITS 32STRUC dirent.d_ino:		resd	1.d_off:		resd	1.d_reclen:	resw	1.d_name:	resb	256ENDSTRUC;; The top word of the origin is the instruction "push byte 1".%define	origin			0x016A0000%define	pathbufsize		4096			; maximum path length%define	direntsbufsize		8192			; a good buffer size;; ebp is used to point to the itoa subroutine and nearby data.%define	DATAOFF(pos)		byte ebp + ((pos) - _ebp_pos_);; The ELF header.		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		dw	(origin & 0x000FFFF)			;   p_vaddr_start:		push	byte 1		push	byte 54					;   p_paddr		jmp	short main		dd	filesize				;   p_filesz		dd	memsize					;   p_memsz		dd	7					;   p_flags		dd	0x1000					;   p_alignphdrsize	equ	$ - phdr;; This is the top-level routine of the program. It parses the;; command-line options, and then calls ls on the remaining arguments.main:;; ebp is initialized as our global pointer into the bss area.		mov	ebp, itoa;; If calling ioctl on stdout returns a non-zero value, then stdout is;; not a tty. This determines whether the default output format is;; columnar (-C) or one-file-per-line (-1).		pop	eax		pop	ebx		mov	ecx, ebx		mov	ch, 0x54		lea	edx, [DATAOFF(pathbuf)]		int	0x80		mov	[DATAOFF(oneperln)], al;; After skipping argc and argv[0], the command-line arguments are;; examined as options until: none are left, an argument that doesn't;; start with a dash is found, or an argument that starts with a;; double-dash is found. Each option maps to a byte that is used as a;; boolean value that is zero by default (with the exception of -1, as;; noted above, and -C, which causes -l and -1 to be turned off if;; they were previously on).		xor	edx, edx		pop	esi		pop	esi.argloop:	pop	esi		or	esi, esi		jz	.noargs		cmp	byte [esi], '-'		jnz	.argloopend		lodsb		cmp	al, [esi]		jz	.argloopquit.optloop:	lodsb		or	al, al		jz	.argloop		lea	edi, [DATAOFF(options)]		lea	ecx, [byte edx + optioncount]		repnz scasb		mov	[DATAOFF(optionflags) + ecx], al		cmp	al, 'C'		jnz	.optloop		mov	[DATAOFF(longdisp)], edx		jmp	short .optloop;; If a double-dash was encountered, then the program skips to the;; next argument. If there are no arguments left, a pointer to the;; string "." is pushed onto the stack. If there is more than one;; argument present at this point, edx will be set to a non-zero;; value..argloopquit:	pop	esi		or	esi, esi		jnz	.argloopend.noargs:	push	byte '.'		mov	esi, esp		push	edx.argloopend:	mov	edx, [esp];; ls is called for each command-line argument remaining. The extra;; return value from ls is discarded, except to cause edx to be;; non-zero after the first iteration (if there is more than one;; iteration.).lsiterate:	call	ls		pop	edx		pop	esi		or	esi, esi		jnz	.lsiterate;; The directory headings flag is turned on, and any subdirectories;; stored from the previous calls to ls are displayed in full.		mov	byte [DATAOFF(dirheads)], ':'		mov	esi, dirqueue		call	lsrecurse;; The last error value, if any, is retrieved, and the program returns;; to the caller.		xchg	eax, ebx		mov	ebx, [DATAOFF(retval)]		int	0x80;; ls produces output for a single file or directory.;;;; input:;; esi = buffer containing file name;; edx = boolean: zero indicates that directories should be expanded;;       in full, non-zero indicates that a directory should be added;;       to the directory queue and nothing should be displayed;;;; output:;; stack = pointer to byte following file name;; all registers (except ebp) are alteredls:;; The filename is copied to a special buffer, and the length is;; determined. The position following the filename in the source;; buffer is saved on the stack above the return value.		lea	edi, [DATAOFF(pathbuf)]		mov	ebx, edi.savenameloop:	lodsb		stosb		or	al, al		jnz	.savenameloop		pop	eax		push	esi		push	eax		mov	esi, ebx		sub	edi, ebx		dec	edi;; lstat is called. If an error is returned, the program returns at;; once. If the file is not a directory, the program jumps to lsfile.;; If the file is a directory and edx is zero, the program jumps to;; lsdir. Otherwise, the program falls through to dirpush.		call	dolstat		jc	quit1		jnz	lsfile		cmp	al, [DATAOFF(hidedirs)]		jnz	lsfile		or	edx, edx		jz	near lsdir;; dirpush adds a directory to the directory queue.;;;; input:;; esi = pathname;;;; output:;; esi = first byte after pathname;; eax, ebx, and edi are altereddirpush:;; The pathname is copied to the end of the directory queue. The;; directory queue is then expanded by calling brk to ensure;; sufficient space for the next call.		mov	edi, [DATAOFF(dirqueuetop)].copypathloop:	lodsb		stosb		or	al, al		jnz	.copypathloop		mov	[DATAOFF(dirqueuetop)], edi		xor	ebx, ebx		lea	eax, [byte ebx + 45]		mov	bh, pathbufsize >> 8		add	ebx, edi		int	0x80quit1:		ret;; lsfile produces output for a single file.;;;; input:;; pathbuf = file's complete pathname;; sts = file's stat information;; esi = filename (minus the path);; edi = length of filename;;;; output:;; all registers (except ebp) are alteredlsfile:;; edi is initialized to point to outbuf, which is where the output;; will be built up. The start of outbuf and the filename's length are;; stored on the stack.		mov	eax, outbuf		push	eax		push	edi		xchg	eax, edi		cdq;; The inode number is displayed if -i was specified.		cmp	dh, [DATAOFF(showinod)]		jz	.noinode		mov	eax, [DATAOFF(sts.st_ino)]		mov	dl, 8		call	ebp		mov	al, ' '		stosb.noinode:;; The size in blocks is displayed if -s was specified.		cmp	dh, [DATAOFF(showblks)]		jz	.noblocks		mov	eax, [DATAOFF(sts.st_blocks)]		shr	eax, 1		mov	dl, 4		call	ebp		mov	al, ' '		stosb.noblocks:;; A whole bunch of code is skipped over unless -l was specified.		cmp	dh, [DATAOFF(longdisp)]		jz	.briefrelay;; The first section of long output displays the mode value as a;; string of diverse characters. The mode is separated into the nine;; basic permission bits (dl plus the carry flag), the three upper;; permission bits (dh), and the top four bits which indicate the file;; type (al). The latter is, after being saved on the stack,;; translated directly into a lowercase letter and added to outbuf.;; ecx is initialized to a pattern which is used to indicate which of;; the nine basic permission bits are execute permissions, as well as;; when all nine bits have been examined.		mov	edx, [DATAOFF(sts.st_mode)]		mov	al, dh		shr	al, 4		push	eax		lea	ebx, [DATAOFF(filetypes)]		xlatb		stosb		lea	ebx, [DATAOFF(permissions)]		mov	ecx, 444q		rcr	dh, 1;; This loop executes once for each basic permission bit, moving each;; bit into the carry flag in turn. al is set to 4, 2, or 1 if the bit;; is set, or 7 if it is turned off. If the bit is an execute;; permission, then the corresponding upper permission bit is also;; examined. If it is set, then an "x" must be changed to an "s" or;; "t", and a "-" to an "S" or "T"..permloop:	mov	al, 7		jnc	.permoff		and	al, cl.permoff:	test	cl, 1		jz	.nosbit		shl	dh, 1		test	dh, 8		jz	.nosbit		add	al, cl		and	al, 0x1F		inc	eax.nosbit:	xlatb		stosb		shr	ecx, 1		jz	.permloopend		rcl	dl, 1				; carry = next bit		jmp	short .permloop.briefrelay:	jmp	short .brief.permloopend:;; The number of hard links, the owner's user id, and the owner's;; group id are each in turn added to outbuf.		lea	ebx, [byte ecx + 3]		lea	edx, [byte ecx + 4]		push	esi		lea	esi, [DATAOFF(sts.st_nlink)].numoutloop:	lodsw		call	ebp		mov	dl, 7		dec	ebx		jnz	.numoutloop		pop	esi;; The file type is retrieved from the stack, and the values;; indicating a character or block device are checked for. If present,;; the file's rdev numbers are added to outbuf; otherwise, the file's;; size is used.		pop	eax		and	al, ~4		cmp	al, 2		mov	eax, [DATAOFF(sts.st_size)]		mov	dl, 10		jnz	.nordev		mov	dl, 5		movzx	eax, byte [DATAOFF(sts.st_rdev + 1)]		call	ebp		mov	al, [DATAOFF(sts.st_rdev)].nordev:	call	ebp;; The programs gets the current time and subtracts the file's;; modification time from it. This value is then subsequently divided;; by 60, 60, and 24, stopping if the quotient ever drops to zero. The;; remainder (or quotient, if it is non-zero after all three;; divisions) is added to outbuf as the file's modification age,;; followed by the appropriate letter to indicate the units. (The xlatb;; at the end works because al is always zero.)		mov	al, 78		mov	ebx, edi		xor	ecx, ecx		int	0x80		mov	eax, [edi]		sub	eax, [DATAOFF(sts.st_mtime)]		mov	ebx, ebp.timingloop:	cdq		dec	ebx		mov	cl, [byte ebx + timeunits - itoa]		or	ecx, ecx		jz	.showtime		div	ecx		or	eax, eax		jnz	.timingloop		xchg	eax, edx.showtime:	mov	dl, 5		call	ebp		xlatb		stosb		mov	al, ' '		stosb;; End of long output..brief:;; The filename's length is retrieved, and the filename is copied into;; outbuf.		pop	ecx		call	copyfilename;; The mode bits are checked to see if the file is a symbolic link.		mov	al, [DATAOFF(sts.st_mode) + 1]		and	al, 0xF0		sub	al, 0xA0		jnz	.nosymlink		cmp	al, [DATAOFF(longdisp)]		jz	.nosymlink;; If it is, and the output is verbose, then the link destination is;; appended to outbuf, prefixed by an arrow. (The top of the directory;; queue is used as a convenient temporary buffer.) Then the original;; filename is given to stat, as opposed to lstat, in order to obtain;; the file type of the link destination.		mov	eax, ' -> '		stosd		lea	eax, [byte ecx + 85]		lea	ebx, [DATAOFF(pathbuf)]		mov	ecx, [DATAOFF(dirqueuetop)]		cdq		mov	dh, pathbufsize >> 8		int	0x80		xchg	eax, ecx		xchg	eax, esi		mov	[esi + ecx], dl		call	copyfilename		xchg	eax, ecx		mov	al, 106		lea	ecx, [DATAOFF(sts)]		int	0x80		or	eax, eax		js	.endentry.nosymlink:;; The file's type is separated out from the other mode bits. If -F;; was specified, and the file type has an associated suffix;; character, this character is added to outbuf immediately following;; the filename. If the file type has no suffix, but is executable, an;; asterisk is used.		mov	eax, [DATAOFF(sts.st_mode) - 2]		shr	eax, 29		cmp	ah, [DATAOFF(showtype)]		jz	.endentry		mov	al, [DATAOFF(suffixes) + eax]		cmp	al, '*'		jnz	.fmtchar		test	byte [DATAOFF(sts.st_mode)], 111q		jz	.endentry.fmtchar:	stosb;; The entry is complete but for the whitespace. If -1 was specified,;; then a final newline is all that is needed..endentry:	mov	al, 10		xor	ebx, ebx		inc	ebx		cmp	bh, [DATAOFF(oneperln)]		jnz	.endline;; Otherwise, the tabstop corresponding to the current cursor position;; is retrieved from xline and is added to the length of the text in;; outbuf (converted to tabstops). If it extends past the tenth;; tabstop, a newline is output to stdout immediately. If it extends;; past the eighth tabstop, a newline is added to outbuf. If the;; tabstop is an odd number, two tabs are added to outbuf. Otherwise,;; one tabstop is added to outbuf. In all cases, xline is updated to;; reflect the position of the cursor after output.		mov	ecx, edi		sub	ecx, [esp]		shr	ecx, 3		inc	ecx		mov	dl, [DATAOFF(xline)]		add	dl, cl		cmp	al, dl		jae	.fitsinline		push	ecx		call	tobol		pop	edx.fitsinline:	mov	al, 9		cmp	al, dl		ja	.roomformore		inc	eax		mov	dl, 0.roomformore:	test	dl, bl		jz	.setxline		stosb		inc	edx.setxline:	mov	[DATAOFF(xline)], dl.endline:

⌨️ 快捷键说明

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