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

📄 proc32.ash

📁 开源的nasm编译器源码,研究编译器原理很有帮且
💻 ASH
字号:
;--------=========xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=========--------;;   Copyright (C) 1999 by Andrew Zabolotny;   Miscelaneous NASM macros that makes use of new preprocessor features; ;   This library is free software; you can redistribute it and/or;   modify it under the terms of the GNU Library General Public;   License as published by the Free Software Foundation; either;   version 2 of the License, or (at your option) any later version.; ;   This library is distributed in the hope that it will be useful,;   but WITHOUT ANY WARRANTY; without even the implied warranty of;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU;   Library General Public License for more details.; ;   You should have received a copy of the GNU Library General Public;   License along with this library; if not, write to the Free;   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.;;--------=========xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=========--------;   The macros in this file provides support for writing 32-bit C-callable;   NASM routines. For a short description of every macros see the;   corresponding comment before every one. Simple usage example:;;	proc	sin,1;		targ	%$angle;		fld	%$angle;		fsin;	endproc	sin%ifndef __PROC32_ASH__%define __PROC32_ASH__[WARNING -macro-selfref];-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   Mangle a name to be compatible with the C compiler; Arguments:;   The name; Example:;		cname (my_func);-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%ifdef EXTERNC_UNDERSCORE		%define	cname(x) _ %+ x%else		%define	cname(x) x%endif;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   Import an external C procedure definition; Arguments:;   The name of external C procedure; Example:;		cextern	printf;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%macro		cextern	1		%xdefine %1 cname(%1)	%ifidni __OUTPUT_FORMAT__,obj		extern	%1:wrt FLAT	%else		extern	%1	%endif%endmacro;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   Export an C procedure definition; Arguments:;   The name of C procedure; Example:;		cglobal	my_printf;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%macro		cglobal	1		%xdefine %1 cname(%1)		global	%1%endmacro;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   Misc macros to deal with PIC shared libraries; Comment:;   Note that we have a different syntax for working with and without;   PIC shared libraries. In a PIC environment we should load first;   the address of the variable into a register and then work through;   that address, i.e: mov eax,myvar; mov [eax],1;   In a non-PIC environment we should directly write: mov myvar,1; Example:;		extvar	myvar;		GetGOT;	%ifdef PIC;		mov	ebx,myvar	; get offset of myvar into ebx;	%else;		lea	ebx,myvar;	%endif;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%ifdef PIC		cextern	_GLOBAL_OFFSET_TABLE_	%macro	GetGOT	0		%ifdef .$proc.stkofs			%assign .$proc.stkofs .$proc.stkofs+4		%endif		call	%$Get_GOT	%$Get_GOT:		pop	ebx		add	ebx,_GLOBAL_OFFSET_TABLE_ + $$ - %$Get_GOT wrt ..gotpc	%endmacro	%macro	extvar	1		cextern	%1		%xdefine %1 [ebx+%1 wrt ..got]	%endmacro%else	%define	GetGOT	%macro	extvar	1		cextern	%1	%endmacro%endif;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   Begin a procedure definition;   For performance reasons we don't use stack frame pointer EBP,;   instead we're using the [esp+xx] addressing. Because of this;   you should be careful when you work with stack pointer.;   The push/pop instructions are macros that are defined to;   deal correctly with these issues.; Arguments:;   First argument - the procedure name;   Second optional argument - the number of bytes for local variables;   The following arguments could specify the registers that should be;   pushed at beginning of procedure and popped before exiting; Example:;   proc	MyTestProc;   proc	MyTestProc,4,ebx,esi,edi;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%macro		proc	1-3+ 0		cglobal	%1		%push	%1		align	16%1:		%xdefine %$proc.name %1	; total size of local arguments		%assign %$proc.locsize (%2+3) & 0xFFFC	; offset from esp to argument		%assign	%$proc.argofs 4+%$proc.locsize	; additional offset to args (tracks push/pops)		%assign	.$proc.stkofs 0	; offset from esp to local arguments		%assign %$proc.locofs 0	; Now push the registers that we should save		%define %$proc.save %3	%if %$proc.locsize != 0		sub	esp,%$proc.locsize	%endif		push	%$proc.save%endmacro;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   Declare an argument passed on stack;   This macro defines two additional macros:;     first (with the name given by first argument) - [esp+xx];     second (with a underscore appended to first argument) - esp+xx; Arguments:;   First argument defines the procedure argument name;   Second optional parameter defines the size of the argument;   Default value is 4 (a double word); Example:;		arg	.my_float;		arg	.my_double,8;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%macro		arg	1-2 4	%ifndef %$proc.argofs		%error	"`arg' not in a proc context"	%else	; Trick: temporary undefine .$proc.stkofs so that it won't be expanded		%assign	%%. .$proc.stkofs		%undef .$proc.stkofs		%xdefine %{1}_ esp+%$proc.argofs+.$proc.stkofs		%xdefine %1 [esp+%$proc.argofs+.$proc.stkofs]		%assign .$proc.stkofs %%.		%assign %$proc.argofs %2+%$proc.argofs	%endif%endmacro;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   Declare an local variable;     first (with the name given by first argument) - [esp+xx];     second (with  a slash prefixing the first argument) - esp+xx; Arguments:;   First argument defines the procedure argument name;   Second optional parameter defines the size of the argument;   Default value is 4 (a double word); Example:;		loc	.int_value;		loc	.double_value,8;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%macro		loc	1-2 4	%ifndef %$proc.locofs		%error	"`loc' not in a proc context"	%elif %$proc.locofs + %2 > %$proc.locsize		%error	"local stack space exceeded"	%else		%assign	%%. .$proc.stkofs		%undef .$proc.stkofs		%xdefine %{1}_ esp+%$proc.locofs+.$proc.stkofs		%xdefine %1 [esp+%$proc.locofs+.$proc.stkofs]		%assign .$proc.stkofs %%.		%assign %$proc.locofs %$proc.locofs+%2	%endif%endmacro;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   Get the type of given size into context-local variable %$type; Arguments:;   Size of type we want (1,2,4,8 or 10); Example:;		type	4	; gives "dword";		type	10	; gives "tword";-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%macro		type	1	%if %1 = 1		%define	%$type byte	%elif %1 = 2		%define	%$type word	%elif %1 = 4		%define	%$type dword	%elif %1 = 8		%define	%$type qword	%elif %1 = 10		%define	%$type tword	%else		%define %$. %1		%error "unknown type for argument size %$."	%endif%endmacro;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   Same as `arg' but prepends "word", "dword" etc (typed arg);     first (with the name given by first argument) - dword [esp+xx];     second (with  a slash prefixing the first argument) - esp+xx; Arguments:;   Same as for `arg'; Example:;		targ	.my_float	; .my_float is now "dword [esp+xxx]";		targ	.my_double,8	; .my_double is now "qword [esp+xxx]";-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%macro		targ	1-2 4	%ifndef %$proc.argofs		%error	"`targ' not in a proc context"	%else		arg	%1,%2		type	%2		%assign	%%. .$proc.stkofs		%undef .$proc.stkofs		%xdefine %1 %$type %1		%assign .$proc.stkofs %%.	%endif%endmacro;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   Same as `loc' but prepends "word", "dword" etc (typed loc);     first (with the name given by first argument) - dword [esp+xx];     second (with  a slash prefixing the first argument) - esp+xx; Arguments:;   Same as for `loc'; Example:;		tloc	int_value;		tloc	double_value,8;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%macro		tloc	1-2 4	%ifndef %$proc.locofs		%error	"`tloc' not in a proc context"	%else		loc	%1,%2		type	%2		%assign	%%. .$proc.stkofs		%undef .$proc.stkofs		%xdefine %1 %$type %1		%assign .$proc.stkofs %%.	%endif%endmacro;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   Finish a procedure;   Gives an error if proc/endproc pairs mismatch;   Defines an label called __end_(procedure name);   which is useful for calculating function size; Arguments:;   (optional) The name of procedure; Example:;   endproc	MyTestProc;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%push	tmp	; trick: define a dummy context to avoid error in next line%macro		endproc	0-1 %$proc.name	%ifndef %$proc.argofs		%error "`endproc' not in a proc context"	%elifnidn %$proc.name,%1		%define %$. %1		%error "endproc names mismatch: expected `%$proc.name'"		%error "but got `%$.' instead"	%elif %$proc.locofs < %$proc.locsize		%error	"unused local space declared (used %$proc.locofs, requested %$proc.locsize)"	%else%$exit:	; Now pop the registers that we should restore on exit		pop	%$proc.save		%if %$proc.locsize != 0		add	esp,%$proc.locsize		%endif		ret__end_%1:		%pop	%endif%endmacro%pop;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   A replacement for "push" for use within procedures; Arguments:;   any number of registers which will be push'ed successively; Example:;		push	eax,ebx,ecx,edx;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%macro		push	0-*; dummy comment to avoid problems with "push" on the same line with a label	%rep	%0		push	%1		%rotate	1		%assign .$proc.stkofs .$proc.stkofs+4	%endrep%endmacro;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   A replacement for "pop" for use within procedures; Arguments:;   any number of registers which will be pop'ed in reverse order; Example:;		pop	eax,ebx,ecx,edx;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%macro		pop	0-*; dummy comment to avoid problems with "pop" on the same line with a label	%rep	%0		%rotate	-1		pop	%1		%assign .$proc.stkofs .$proc.stkofs-4	%endrep%endmacro;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   Replacements for "pushfd" and "popfd" that takes care of esp; Example:;		pushfd;		popfd;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%macro		pushfd	0		pushfd		%assign .$proc.stkofs .$proc.stkofs+4%endmacro%macro		popfd	0		popfd		%assign .$proc.stkofs .$proc.stkofs-4%endmacro;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   Exit from current procedure (optionally on given condition); Arguments:;   Either none or a condition code; Example:;		exit;		exit	nz;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%macro		exit	0-1 mp		j%1	near %$exit%endmacro;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   start an conditional branch; Arguments:;   A condition code;   second (optional) argument - "short" (by default - "near"); Example:;		if	nz;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%macro		if	1-2 near; dummy comment to avoid problems with "if" on the same line with a label		%push	if		j%-1	%2 %$elseif%endmacro;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   define the "else" branch of a conditional statement; Arguments:;   optionaly: "short" if jmp to endif is less than 128 bytes away; Example:;		else;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%macro		else	0-1	%ifnctx if		%error	"`else' without matching `if'"	%else		jmp	%1 %$endif%$elseif:		%define	%$elseif_defined	%endif%endmacro;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----; Summary:;   Finish am conditional statement; Arguments:;   none; Example:;		endif;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----%macro		endif	0	%ifnctx if		%error	"`endif' without matching `if'"	%else		%ifndef %$elseif_defined%$elseif:		%endif%$endif:		%pop	%endif%endmacro%endif ; __PROC32_ASH__

⌨️ 快捷键说明

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