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

📄 libc.asm

📁 A simple C compiler source code.
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;Copyright (C) 1999-2002 Konstantin Boldyshev <konst@linuxassembly.org>;Copyright (C) 1999 Cecchinel Stephan <inter.zone@free.fr>;;$Id: libc.asm,v 1.15 2002/06/11 08:38:39 konst Exp $;;hackers' libc;;Yes, this is the most advanced libc ever seen.;It uses advanced technologies which are possible only with assembly.;Two main features that make this libc outstanding:;1) calling convention can be configured AT RUNTIME (cdecl is default);2) THE smallest size;;It uses mixed code-data database approach for syscalls,;resulting in extremely small size.;;Well, there's still a lot of work to be done.;;0.01: 10-Sep-1999	initial alpha pre beta 0 non-release;0.02: 24-Dec-1999	first working version;0.03: 21-Feb-2000	fastcall support;0.04: 20-Jul-2000	fixed stupid bug/misprint, merged clib.asm & string.asm;			printf();0.05: 16-Jan-2001	usual functions now work with both cdecl and fastcall,;			added PIC support (and __GET_GOT macro),;			added __ADJUST_CDECL3 macro,;			syscall mechanism rewritten (size improved),;			separated and optimized sprintf(),;			printf() implemented via sprintf(),;			lots of other various fixes (KB);			finally ready for additions and active development.;0.06: 28-Jan-2001	added __start_main - it is called from stub in order;			to prepare main() arguments (argc, argv, envp),;			PIC fixes (KB);0.07: 25-Feb-2001	added __VERBOSE__, memcmp(), getenv() (KB);0.08: 20-Jan-2002	strlen() bugfix, various fixes (KB);0.09: 03-Mar-2002	__start_main fastcall fix (KB)%undef __ELF_MACROS__%include "system.inc"%define __PIC__		;build PIC version;%define	__VERBOSE__	;treat stack with care;; macro used for function declaration;%macro _DECLARE_FUNCTION 1-*%rep %0    global %1:function%rotate 1%endrep%endmacro;; macro used for syscall declaration;;%1	syscall name;%2	number of parameters;;Ok, what is written below?;Yes - a really dirty trick, but it really saves size.;This is the thing I like assembly for,;and this why this libc is the most advanced :);;This macro generates the following code:;six bytes	-	call instruction;one byte	-	number of syscall parameters (<0 means always cdecl);one byte	-	syscall number (two bytes on BSD systems);;So, each syscall will take only 8 bytes (9 bytes on BSD systems);in executable image. We use call instruction to push return address,;and then find out syscall number and number of parameters using;this address in __system_call function. ret instructions is also;missing, because we will handle correct return in __system_call too.%macro _DECLARE_SYSCALL 2    global %1:function%1: call	__system_call    db	%2	;number of parameters%ifndef	__BSD__    db	SYS_%{1};syscall number%else    dw	SYS_%{1}%endif%endmacro;;PIC handling;%define	__EXT_VAR(x) [ebx + (x) wrt ..got]%define	__INT_VAR(x) ebx + (x) wrt ..gotoff%macro __GET_GOT 0	call	__get_GOT%%get_GOT:%define gotpc %%get_GOT wrt ..gotpc	add	ebx,_GLOBAL_OFFSET_TABLE_ + $$ - gotpc%undef gotpc%endmacro;adjust cdecl call (1 - 3 parameters);;%1		stack frame to add;%2 - %4	registers%macro	__ADJUST_CDECL3	2-4;	_mov	%2,eax;%if %0>2;	_mov	%3,edx;%if %0>3;	_mov	%4,ecx;%endif;%endif%ifdef __PIC__	push	ebx	__GET_GOT	mov	ebx,__EXT_VAR(__cc)	cmp	byte [ebx],0	pop	ebx%else	cmp	byte [__cc],0%endif	jnz	%%fc	mov	%2,[esp + %1 + 4 ]%if %0>2	mov	%3,[esp + %1 + 8 ]%if %0>3	mov	%4,[esp + %1 + 12]%endif%endif%%fc:%endmacro;;for accessing registers after pusha;%define	__ret	esp+4*8%define	__eax	esp+4*7%define	__ecx	esp+4*6%define	__edx	esp+4*5%define	__ebx	esp+4*4%define	__esp	esp+4*3%define	__ebp	esp+4*2%define	__esi	esp+4*1%define	__edi	esp+4*0CODESEG%ifdef __PIC____get_GOT:	mov	ebx,[esp]	ret%endifSTART:%ifdef __PIC__	__GET_GOT	lea	ecx,[__INT_VAR(__libc_banner)]%else	mov	ecx,__libc_banner%endif	sys_write STDOUT,EMPTY,__LIBC_BANNER_LEN	sys_exit 0__libc_banner		db	"a r e   y o u   s i c k ?", __n__LIBC_BANNER_LEN	equ	$ - __libc_bannerextern _GLOBAL_OFFSET_TABLE_;**************************************************;*             INTERNAL FUNCTIONS                 *;**************************************************;;perform a system call (up to 6 arguments);__system_call:	pusha	mov	eax,[__esp]		;load number of syscall args into eax	mov	eax,[eax]	movzx	eax,byte [eax]	test	al,al	jz	.ssn			;no args%ifdef	__VERBOSE__	jns	.sk1			;usual call	neg	al			;always cdecl call	jmps	.cdecl%else	js	.cdecl%endif.sk1:%ifdef __PIC__	__GET_GOT	mov	ebx,__EXT_VAR(__cc)	cmp	byte [ebx],0%else	cmp	byte [__cc],0%endif	jnz	.fc%define _STACK_ADD 8 + 4*8%macro _JZ_SSN_ 0%ifdef	__VERBOSE__	dec	eax	jz	.ssn%endif%endmacro.cdecl:	mov	ebx,[esp + _STACK_ADD]		;1st arg	_JZ_SSN_	mov	ecx,[esp + _STACK_ADD + 4]	;2nd arg	_JZ_SSN_	mov	edx,[esp + _STACK_ADD + 8]	;3rd arg	_JZ_SSN_	mov	esi,[esp + _STACK_ADD + 12]	;4th arg	_JZ_SSN_	mov	edi,[esp + _STACK_ADD + 16]	;5th arg	_JZ_SSN_	mov	ebp,[esp + _STACK_ADD + 20]	;6th arg	jmps	.ssn.fc:	mov	ebx,[__eax]			;1st arg	_JZ_SSN_	xchg	ecx,edx				;2nd & 3rd arg	_JZ_SSN_	_JZ_SSN_	mov	esi,[esp + _STACK_ADD]		;4th arg	_JZ_SSN_	mov	edi,[esp + _STACK_ADD + 4]	;5th arg	_JZ_SSN_	mov	ebp,[esp + _STACK_ADD + 8]	;6th arg%undef _STACK_ADD.ssn:	mov	eax,[__esp]		;set syscall number	mov	eax,[eax]%ifndef	__BSD__	movzx	eax,byte [eax + 1]	;return address + 1%else	movzx	eax,word [eax + 1]	;return address + 1%endif	sys_generic	cmp	eax,-4095	jb	.leave;	test	eax,eax;	jns	.leave	neg	eax%ifdef __PIC__	__GET_GOT	mov	ebx,__EXT_VAR(errno)	mov	[ebx],eax%else	mov	[errno],eax%endif	or	eax,byte -1.leave:	mov	[__eax + 4],eax		;replace return address with eax	popa	pop	eax			;now get it back	ret				;and return to previous caller;;;_DECLARE_SYSCALL	open,	-3	;<0 means always cdecl_DECLARE_SYSCALL	close,	1_DECLARE_SYSCALL	read,	3_DECLARE_SYSCALL	write,	3_DECLARE_SYSCALL	lseek,	3_DECLARE_SYSCALL	chmod,	2_DECLARE_SYSCALL	chown,	2_DECLARE_SYSCALL	pipe,	1_DECLARE_SYSCALL	link,	2_DECLARE_SYSCALL	symlink,2_DECLARE_SYSCALL	unlink,	1_DECLARE_SYSCALL	mkdir,	1_DECLARE_SYSCALL	rmdir,	1_DECLARE_SYSCALL	exit,	1_DECLARE_SYSCALL	fork,	0_DECLARE_SYSCALL	execve,	3_DECLARE_SYSCALL	uname,	1_DECLARE_SYSCALL	ioctl,	3_DECLARE_SYSCALL	alarm,	1_DECLARE_SYSCALL	nanosleep,	2_DECLARE_SYSCALL	kill,	2_DECLARE_SYSCALL	signal,	2_DECLARE_SYSCALL	wait4,	4;_DECLARE_SYSCALL	stat,	2_DECLARE_SYSCALL	fstat,	2_DECLARE_SYSCALL	lstat,	2_DECLARE_SYSCALL	getuid,	0_DECLARE_SYSCALL	getgid,	0_DECLARE_FUNCTION	_fastcall_DECLARE_FUNCTION	memcpy, memset, memcmp_DECLARE_FUNCTION	strlen_DECLARE_FUNCTION	strtol_DECLARE_FUNCTION	itoa_DECLARE_FUNCTION	printf, sprintf_DECLARE_FUNCTION	getenv_DECLARE_FUNCTION	__start_main;;;ebp	-	main() address__start_main:	pop	ebp			;main() address	pop	eax			;argc	lea	ecx,[esp + eax * 4 + 4]	;**envp%ifdef	__PIC__	__GET_GOT	mov	ebx,__EXT_VAR(__envp)	mov	[ebx],ecx%else	mov	[__envp],ecx%endif	mov	edx,esp			;**argv	push	ecx	push	edx	push	eax	call	ebp	push	eax	call	exit;**************************************************;*          GLOBAL LIBRARY FUNCTIONS              *;**************************************************;void fastcall(int regnum);;set fastcall/cdecl calling convention;note: always uses fasctall convention;;<EAX	regnum_fastcall:%ifdef	__PIC__	push	ebx	__GET_GOT	mov	ebx,__EXT_VAR(__cc)	mov	[ebx],eax	pop	ebx%else	mov	[__cc],eax%endif	ret;void memset(void *s, int c, size_t n);;fill an array of memory;;<EDX	*s;<AL	c;<ECX	nmemset:	push	edx	push	ecx	push	eax	xchg	eax,edx	__ADJUST_CDECL3 4*3,edx,eax,ecx.real:%if __OPTIMIZE__=__O_SPEED__	cmp	ecx,byte 20	;if length is below 20 , better use byte fill	jl	.below20	mov	ah,al		;expand al to eax like alalalal	push	ax	shl	eax,16	pop	ax.lalign:	test	dl,3		;align edx on a 4 multiple	jz	.align1	mov	[edx],al	inc	edx	dec	ecx	jnz	.lalign	jmps	.memfin.align1:	push	ecx        shr	ecx,3		;divide ecx by 8	pushf.boucle:	mov	[edx],eax	;then fill by 2 dword each times	mov	[edx+4],eax	;it is faster than stosd (on PII)	add	edx,byte 8	dec	ecx	jnz	.boucle	popf	jnc	.boucle2	mov	[edx],eax	add	edx,byte 4.boucle2:	pop	ecx        and	ecx,byte 3        jz	.memfin.below20:	mov	[edx+ecx-1],al	dec	ecx	jnz	.below20.memfin:%else		;__O_SIZE__	push	edi	cld	mov	edi,edx	rep	stosb	pop	edi%endif		;__OPTIMIZE__	pop	eax	pop	ecx	pop	edx	ret;void *memcpy(void *dest,const void *src, size_t n);;<EDI	*dest;<ESI	*src;<ECX	nmemcpy:%if __OPTIMIZE__=__O_SPEED__%define	_STACK_ADD 4*3	push	ecx	push	edi	push	esi%else%define	_STACK_ADD 4*8	pusha%endif	mov	edi,eax	mov	esi,edx	__ADJUST_CDECL3 _STACK_ADD,edi,esi,ecx.real:	cld	rep	movsb%if __OPTIMIZE__=__O_SPEED__	pop	esi	pop	edi	pop	ecx%else	popa%endif%undef	_STACK_ADD	ret;int memcmp(void *s1, void *s2, size_t n);;compare memory areas;;<ESI	*s1;<EDI	*s2;<ECX	nmemcmp:	push	esi	push	edi	push	ecx	__ADJUST_CDECL3 4*3,esi,edi,ecx.real:	cld	rep	cmpsb	jz	.ret	sbb	eax,eax	or	eax,byte 1.ret:	pop	ecx	pop	edi	pop	esi	ret;char *getenv(char *);;<ESI	*sgetenv:	pusha	mov	edi,eax	__ADJUST_CDECL3 4*8,edi

⌨️ 快捷键说明

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