         ;     THE EZ_ASM.MAC LIBRARY OF MACROS WAS DEVELOPED
         ;                          BY
         ;                      GENE BROWN
         ;                          FOR
         ;                    C SOURCE, INC.
	    ; 
         ;     EZ_ASM CAN BE PURCHASED FROM C SOURCE FOR $65
         ;   INCLUDES A TYPESET MANUAL AND UPDATE NOTIFICATION
	    ; 
         ;                       C SOURCE
         ;                   12801 FROST ROAD
         ;                KANSAS CITY, MO. 64138
         ;                    (816) 353-8808
	    ; 
         ;             PLEASE RESPECT OUR LABOR AND
         ;         DO NOT REMOVE THIS COPYRIGHT NOTICE.

IFDEF @Version
     @MASM_VER EQU  600
	OPTION NOKEYWORD:<EXTERN .IF>
ELSE
	@MASM_VER EQU	0
ENDIF

IF1
	%OUT EZ_ASM VERSION 1.0 BY C SOURCE, INC -- COPYRIGHT (C) 1986, 1987
	ENDIF
	

		; +++++ START CONFIGURE EZ_ASM.MAC +++++
		
		;       TO CONFIGURE EZ_ASM.MAC FOR YOUR ENVIRONMENT YOU MUST:       
		;				A. SPECIFY THE COMPILER 
		;				B. SPECIFY THE VERSION #
		;				C. SPECIFY THE MEMORY MODEL
		;
		; 		    ALL THREE OF THESE ARE DIRECTLY BELOW


._YES		= 1
._NO			= 0

._NONE		= 0
._LEADING		= 1
._TRAILING	= 2

._SMALL_MODEL	 = 1
._S_MODEL		 = 1
._MEDIUM_MODEL	 = 2
._P_MODEL		 = 2
._COMPACT_MODEL = 3
._D_MODEL		 = 3	
._LARGE_MODEL	 = 4
._L_MODEL		 = 4
._HUGE_MODEL	 = 5
                
._SMALL_DATA	 = 1
._MEDIUM_DATA	 = 2
._LARGE_DATA	 = 3
                
._SMALL_CODE	 = 5
._LARGE_CODE	 = 6
                
._NEAR_PTR	 = 2
._FAR_PTR		 = 4

._FCN_PTR	  =	100H
._SMALL_CODE_PTR =	._FCN_PTR OR ._NEAR_PTR
._LARGE_CODE_PTR =  ._FCN_PTR OR ._FAR_PTR
NEAR_CODE_PTR    = ._SMALL_CODE_PTR
FAR_CODE_PTR     = ._LARGE_CODE_PTR


._DATA_TYPE	  =	200H
._SMALL_DATA_PTR =	._DATA_TYPE OR ._NEAR_PTR
._LARGE_DATA_PTR =  ._DATA_TYPE OR ._FAR_PTR

.$RAX =    1H
.$RBX =    2H
.$RCX =    4H
.$RDX =    8H
.$RSI =   10H
.$RDI =   20H
.$RBP =   40H
.$RIP =   80H
.$RSP =  100H
.$RSS =  200H
.$RDS =  400H
.$RES =  800H
.$RCS = 1000H

.$RF_SI =   8000H
.$RF_DI =   8000H
.$RF_ES =   8000H

.$PF_SI = .$RSI    
.$PF_DI = .$RDI   
.$PF_ES = .$RES


.xC_ARGS    = 8000H
.xPOP_ARGS  = 4000H
.xFAR       = 2000H
.xIMPORT    = 1000H
.xCS_STATIC = 0E00H
.xSTATIC    = 0C00H
.xRPTR      = 0A00H
.xLABEL     = 0800H
.xREG       = 0400H
.xCONSTANT  = 0600H
.xSTACK     = 0200H
            
.xFAR_EXTERN  = 3000H		; .xFAR + .xIMPORT
.xEXTERN_DATA = 1C00H         ; .xIMPORT + .xSTATIC
.xEXTERN_FCN  = 1800H         ; .xIMPORT + .xLABEL

.xFCN_TYPE   = 0C000H
.xDATA_TYPE  = 0E00H
.xDATA_SIZE  = 0FH

.IDKONS	= .xCONSTANT
.IDCHAR	= 1
.ID_INT	= 2
.IDLONG	= 4
.IDDATA_PTR 	= (DATA_PTR AND 7H)
.IDCODE_PTR	= (CODE_PTR AND 7H)
.IDRPTR		= 0A00H  
.IDRPTR_CHAR	= 0A01H
.IDRPTR_INT	= 0A02H
.IDRPTR_LONG	= 0A04H 
.IDRPTR_DPTR	= 0A00H + (DATA_PTR AND 7H)
        
.IDAX =  412H
.IDBX =  422H
.IDCX =  432H
.IDDX =  442H
.IDSI =  452H
.IDDI =  462H
.IDSP =  472H
.IDIP =  482H
.IDBP =  492H
.IDCS =  4A2H
.IDSS =  4B2H
.IDDS =  4C2H
.IDES =  4D2H

.IDAH =  411H
.IDAL =  411H
.IDBH =  421H
.IDBL =  421H
.IDCH =  431H
.IDCL =  431H
.IDDH =  441H
.IDDL =  441H

.?NEAR   = 1
.?FAR    = 2
.?STATIC = 4
.?C	    = .xC_ARGS
.?PASCAL = .xPOP_ARGS
.?CP	    = .xC_ARGS + .xPOP_ARGS
.?NF     = 3				

			; +++++ START EZ_ASM MACROS +++++
			
				; VALUES FOR POSSIBLE DATA TYPES
CHAR	= 1
_INT = 2
NEAR_PTR = 2
LONG = 4
FAR_PTR = 4 
FLOAT = 4
DOUBLE = 8

KONS = 079H
STRING = 5		; ONLY USED FOR STATIC MACRO
FCN = 3			; ONLY USED IN EXTERN MACRO



               ; A. SPECIFY THE COMPILER AND MEMORY MODEL


.$FILE_IS_INCLUDED = ._NO

.$DISPLAY_LEVEL = 0				; **** DEFAULT DISPLAY LEVEL ****
.$MEMORY_MODEL = ._SMALL_MODEL;		; **** DEFAULT MEMORY MODEL ****
.$NEW_LEVEL = 0

IFDEF EZ 
	.$NEW_LEVEL = 1
	IFDEF MS
		.$MEMORY_MODEL = ._SMALL_MODEL
		ENDIF
	IFDEF MC
		.$MEMORY_MODEL = ._COMPACT_MODEL
		ENDIF
	IFDEF MD
		.$MEMORY_MODEL = ._COMPACT_MODEL
		ENDIF
	IFDEF MM
		.$MEMORY_MODEL = ._MEDIUM_MODEL
		ENDIF
	IFDEF MP
		.$MEMORY_MODEL = ._MEDIUM_MODEL
		ENDIF
	IFDEF ML
		.$MEMORY_MODEL = ._LARGE_MODEL
		ENDIF
	IFDEF MB
		.$MEMORY_MODEL = ._LARGE_MODEL
		ENDIF
	IFDEF MH
		.$MEMORY_MODEL = ._HUGE_MODEL
		ENDIF
	
	IFDEF CHC
		.$FILE_IS_INCLUDED = ._YES
	     IFDEF ML
	     	.$MEMORY_MODEL = ._HUGE_MODEL
	     	ENDIF
	     INCLUDE HC.MAC
		ENDIF

	IFDEF CMSC
		.$FILE_IS_INCLUDED = ._YES
	     INCLUDE MSC.MAC
		ENDIF
	IFDEF CTPAS
		.$FILE_IS_INCLUDED = ._YES
	     INCLUDE TPASCAL.MAC
		ENDIF
	IFDEF CZTC
		.$FILE_IS_INCLUDED = ._YES
	     INCLUDE ZTC.MAC
	     ENDIF
	IFDEF CTUR
		.$FILE_IS_INCLUDED = ._YES
	     INCLUDE TURBO_C.MAC
		ENDIF
	IFDEF ATASM
		MASM51
		QUIRKS
	     ENDIF
	IFDEF CC86
		.$FILE_IS_INCLUDED = ._YES
	     INCLUDE C86.MAC
	     ENDIF
	
	ENDIF

IF (.$FILE_IS_INCLUDED EQ ._NO)
     INCLUDE MSC.MAC                   ; **** DEFAULT COMPILER ****
     ENDIF
    
IFDEF EZ
     IFDEF YBP
          .$$ALWAYS_SET_NEW_STACK_FRAME = ._YES
          .$NEW_LEVEL = 2
          ENDIF
     IFDEF NBP
          .$$ALWAYS_SET_NEW_STACK_FRAME = ._NO
          .$NEW_LEVEL = 2
          ENDIF
     IFDEF YCS
		.$$CHECK_STACK = ._YES
          .$NEW_LEVEL = 2
		ENDIF
     IFDEF NCS
		.$$CHECK_STACK = ._NO
          .$NEW_LEVEL = 2
		ENDIF
	IFDEF Y286
	     .$$USE_286_INSTRUCTION_SET = ._YES
          .$NEW_LEVEL = 2
	     ENDIF
	IFDEF N286
	     .$$USE_286_INSTRUCTION_SET = ._NO
          .$NEW_LEVEL = 2
	     ENDIF
	IFDEF DL1
		.$DISPLAY_LEVEL = 1
		ENDIF
	IFDEF DL2
		.$DISPLAY_LEVEL = 2
		ENDIF

	IF (.$NEW_LEVEL GT .$DISPLAY_LEVEL)
		.$DISPLAY_LEVEL = .$NEW_LEVEL
		ENDIF
		
	ENDIF

IF (.$$USE_286_INSTRUCTION_SET)
	.286c
	ENDIF

.$MODULE_IS_DEFINED = ._NO;

DEFINE_MODULE	MACRO	MODULE_NAME

	NAME				MODULE_NAME
	
	CODE_PTR = 0;
	DATA_PTR = 0;
	
     .$$SET_MEM_MODEL
	DEFINE_DATA_SEG	MODULE_NAME
	START_DATA
	END_DATA
	DEFINE_CODE_SEG	MODULE_NAME
	START_CODE
	END_CODE
	
	
	IF (.$DISPLAY_LEVEL GT 0)
	     .$DISPLAY_MACRO_SPECS
		ENDIF

	IF (.$$DATA_SIZE EQ ._SMALL_DATA)
		.$RL_DS =   0
		.$Rl_ds =   0
	ELSE
		.$RL_DS =   .$RDS
		.$Rl_ds =   .$RDS
	     ENDIF
	
     .$$SET_CHECK_STACK
	.$MODULE_IS_DEFINED = ._YES;
	
	ENDM

L_DS	EQU DS
l_ds	EQU DS

.$DISPLAY_MACRO_SPECS MACRO
	IF1
     	.$$DISPLAY_COMPILER_AND_MEMORY_MODEL
		ENDIF

	IF (.$DISPLAY_LEVEL EQ 2)
		IF2
			%OUT
			%OUT ++++ DEFAULT SWITCH SETTINGS ++++
			ENDIF
		.@SHOW_FCN_DFLTS %.$$ALWAYS_SET_NEW_STACK_FRAME, %.$$CHECK_STACK, %.$$USE_286_INSTRUCTION_SET, %.$$RESET_DS
		IF2
			%OUT
			%OUT ++++ PROLOGUE REGISTER SETTINGS ++++
			ENDIF
	     .@SHOW_PRO_DFLTS %.$$SAVE_SI, %.$$SAVE_DI, %.$$SAVE_ES
	     IF2
	     	%OUT
	     	ENDIF
		ENDIF

	.@SHOW_FCN_DFLTS MACRO A1, A2, A3, A4
		%OUT ALWAYS PRESERVE BP = A1     CHECK STACK = A2
		%OUT USE 286 INSTRUCTIONS = A3   RESET DS ON FCN ENTRY = A4
		ENDM

	.@SHOW_PRO_DFLTS MACRO A1, A2, A3
		%OUT IF (VALUE > 0) THEN PROLOGUE WILL NOT PRESERVE THE NAMED REGISTER
		%OUT PRESERVE:  SI = A1     DI = A2     ES = A3
		ENDM

	ENDM


.$C_NAMES	MACRO NAME1			; MODIFY PUBLIC NAME FOR COMPILER CONVENTION
	
	IFNB <NAME1>
		IF (.$$UNDERSCORE EQ ._LEADING) 
		     NAME1  EQU _&NAME1
			ENDIF

		IF (.$$UNDERSCORE EQ ._TRAILING)
		     NAME1  EQU  NAME1&_ 
			ENDIF
		
		ENDIF
	
	ENDM

.$IS_EXTERN_DECLARATION = ._NO
.$IS_GLOBAL_DECLARATION = ._NO

EXTERN	MACRO  DATA_TYPE, NAMES, ERR_NAMES
	
	IF1
		IFNB <ERR_NAMES>
			%OUT EZ_ASM Error #4: EXTERN - `NAMES': Missing < >s around name list
			ENDIF
		
		IF (.$IN_FCN_MACRO EQ ._YES)
			%OUT EZ_ASM Error #9: EXTERN - `NAMES': Must not be inside START_FCN/END_FCN pair
			ENDIF		
		ENDIF
	
	IF ((DATA_TYPE EQ FCN) OR (DATA_TYPE EQ CODE_PTR))
		.$IS_EXTERN_DECLARATION = ._YES
		IRP	VAR_NAME, <NAMES>
			.$SET_FCN_DECL .$STATIC_FCN, 0, DATA_TYPE, VAR_NAME
			ENDM
		.$IS_EXTERN_DECLARATION = ._NO
	ELSE
		IRP	VAR_NAME, <NAMES>
	          .$SET_FCN_DECL .$EXTERN_DATA, 0, DATA_TYPE, VAR_NAME
	          ENDM
		ENDIF
	
	ENDM


.$EXTERN_DATA MACRO DATA_TYPE, VAR_NAME, FORCE_ATTR

	DATA_TYPE = DATA_TYPE AND 0FH
	.@DATA_ATTR = .$$DFLT_DATA_ATTR + .xEXTERN_DATA + DATA_TYPE
	
     IF (FORCE_ATTR NE 0)
     	.$SET_FORCE_ATTR FORCE_ATTR, .@DATA_ATTR
     	ENDIF
		
	IF (.$$UNDERSCORE EQ ._LEADING)
     	.$EXTERN   DATA_TYPE, _&VAR_NAME
     	ENDIF
	IF (.$$UNDERSCORE EQ ._TRAILING)
     	.$EXTERN   DATA_TYPE, VAR_NAME&_
     	ENDIF
	IF (.$$UNDERSCORE EQ ._NONE)
     	.$EXTERN   DATA_TYPE, VAR_NAME
     	ENDIF
	
	IF ((.@DATA_ATTR AND .xFAR) EQ .xFAR)
		START_DATA
		.$SEG&VAR_NAME	DW	SEG VAR_NAME
		END_DATA
		ENDIF
			
	.$C_NAMES  &VAR_NAME
	.ID&VAR_NAME = .@DATA_ATTR 
	.$SVAR .ID&VAR_NAME, %.@DATA_ATTR 
     ENDM

.$SVAR MACRO NAME, VAL
     ;%OUT EXTERN -- NAME = VAL
	ENDM

.$EXTERN	MACRO  DATA_TYPE, NAME1

	IFNB <NAME1>
		
		IF	(DATA_TYPE EQ CHAR)
			EXTRN	NAME1:BYTE
		     EXITM
			ENDIF
		
		IF	(DATA_TYPE EQ _INT)   
			EXTRN	NAME1:WORD
			EXITM
			ENDIF              
	
 		IF	(DATA_TYPE EQ	LONG)
 			EXTRN	NAME1:DWORD
 			EXITM
 			ENDIF
 
		%OUT EZ_ASM Error #2: EXTERN - `NAME1': Unknown data type
		
		ENDIF
	ENDM


.$STATIC_FCN MACRO DATA_TYPE, VAR_NAME, FORCE_ATTR, VAL
	
	.@FCN_ATTR = .$$DFLT_CODE_ATTR
	IF (DATA_TYPE AND ._FCN_PTR)
	     .@FCN_ATTR = (.$$DFLT_CODE_ATTR AND .xFCN_TYPE) + .$$DFLT_DATA_ATTR
	    	IF ((DATA_TYPE EQ FCN) AND (.$LATTICE_P_MODEL EQ ._YES))
	    		.@FCN_ATTR = .@FCN_ATTR + .xFAR
	    		ENDIF
		ENDIF
     
     .$SVAR P1, %.@FCN_ATTR
     
     IF (FORCE_ATTR NE 0)
     	.$SET_FORCE_ATTR FORCE_ATTR, .@FCN_ATTR
     	ENDIF
     
     .$SVAR P2, %.@FCN_ATTR
	
	IF ((.$IS_EXTERN_DECLARATION + .$IS_GLOBAL_DECLARATION) EQ 0)
	     .$_STATIC_FCN VAR_NAME, .@FCN_ATTR, DATA_TYPE, VAR_NAME, VAL
	ELSE
		IF (.$$UNDERSCORE EQ ._LEADING)
	     	.$_STATIC_FCN _&VAR_NAME, .@FCN_ATTR, DATA_TYPE, VAR_NAME, VAL
	     	ENDIF
		IF (.$$UNDERSCORE EQ ._TRAILING)
	     	.$_STATIC_FCN   VAR_NAME&_, .@FCN_ATTR, DATA_TYPE, VAR_NAME, VAL
	     	ENDIF
		IF (.$$UNDERSCORE EQ ._NONE)
	     	.$_STATIC_FCN   VAR_NAME, .@FCN_ATTR, DATA_TYPE, VAR_NAME, VAL
	     	ENDIF
	     ENDIF
			
	.$C_NAMES VAR_NAME
	.ID&VAR_NAME = .@FCN_ATTR OR .$DATA_ID 
     .$SVAR .ID&VAR_NAME, %.ID&VAR_NAME
     .$SVAR FCN_ATTR, %.@FCN_ATTR
     ENDM                 

		
.$_STATIC_FCN MACRO NAME, FCN_ATTR, DATA_TYPE, BARE_NAME, VAL
	
	IF (.$IS_EXTERN_DECLARATION EQ ._NO)
          .@SIZE = DATA_TYPE AND 7
          IF (.$IS_GLOBAL_DECLARATION EQ ._YES)
			PUBLIC NAME
			ENDIF
	     IF ((.$LATTICE_P_MODEL EQ ._YES) AND (.$IS_GLOBAL_DECLARATION EQ ._YES))
			.X&VARNAME  DW CS_LBL:VAL, SEG VAL
			NAME   DW OFFSET .X&VARNAME
		ELSE 
			IF (.@SIZE EQ _INT)
				NAME DW	CS_LBL:VAL
			ELSE
				NAME DD    VAL
				ENDIF
			ENDIF
		.$DATA_ID = .xSTATIC + .@SIZE 
		FCN_ATTR = FCN_ATTR AND (NOT .xFAR);
		EXITM
		ENDIF

	IF (DATA_TYPE AND ._FCN_PTR)
		IF (DATA_TYPE AND _INT)
			EXTRN    NAME:WORD
		ELSE
			EXTRN	NAME:DWORD
			ENDIF
		
		IF (FCN_ATTR AND .xFAR)
			START_DATA
			  .$SEG&BARE_NAME DW	SEG BARE_NAME
			END_DATA
			ENDIF
			
		.$DATA_ID = .xSTATIC + (DATA_TYPE AND 7)
		EXITM
		ENDIF
	
	.$DATA_ID = .xLABEL
	IF ((FCN_ATTR AND .xFAR) EQ ._NO)
		EXTRN NAME:NEAR
	ELSE
		EXTRN NAME:FAR
		ENDIF
	ENDM
      


GLOBAL MACRO DATA_TYPE, VAR_NAME, VAL, ERR_VAL
	
	IF1
		.$DARG_CHK GLOBAL, <VAR_NAME>, <VAL>, <ERR_VAL>
		ENDIF

     START_DATA
     
	.$IS_GLOBAL_DECLARATION = ._YES
	
	IF ((DATA_TYPE AND ._FCN_PTR) EQ ._FCN_PTR)
	     .$DEFINE_DATA_ITEM GLOBAL, DATA_TYPE, <VAR_NAME>, <VAL>
	ELSE
		IF (.$$UNDERSCORE EQ ._LEADING)
		     PUBLIC _&VAR_NAME
		     .$DEFINE_DATA_ITEM GLOBAL, DATA_TYPE, _&VAR_NAME, <VAL>
	          ENDIF
	     
	     IF (.$$UNDERSCORE EQ ._TRAILING)
	     	PUBLIC VAR_NAME&_
	          .$DEFINE_DATA_ITEM GLOBAL, DATA_TYPE, VAR_NAME&_, <VAL>
	          ENDIF
	     
	     IF (.$$UNDERSCORE EQ ._NONE)
	     	PUBLIC VAR_NAME
	          .$DEFINE_DATA_ITEM GLOBAL, DATA_TYPE, VAR_NAME, <VAL>
	          ENDIF
		
	     .$C_NAMES VAR_NAME
	     
	     ENDIF
		
	END_DATA 
	
	.$IS_GLOBAL_DECLARATION = ._NO
     IF (DATA_TYPE NE CODE_PTR)
     	.ID&VAR_NAME = .xSTATIC + (DATA_TYPE AND 0FH)
     	ENDIF
     
     ENDM
     
     
CS_STATIC MACRO  DATA_TYPE, VAR_NAME, VAL, ERR_VAL;
	
	IF1
		.$DARG_CHK CS_STATIC, VAR_NAME, <VAL>, <ERR_VAL>
		ENDIF
	
	START_CODE
	.$DEFINE_DATA_ITEM CS_STATIC, DATA_TYPE, <VAR_NAME>, <VAL>
	END_CODE
	
	IF (DATA_TYPE NE CODE_PTR)
		.ID&VAR_NAME = .xCS_STATIC + (DATA_TYPE AND 0FH)
		ENDIF
	ENDM


.$DARG_CHK MACRO MACNAME, VAR_NAME, VAL, ERR_VAL
	IFNB <ERR_VAL>
		%OUT EZ_ASM Error #4: MACNAME - `VAR_NAME': Missing < >s around initialization array
		ENDIF
	IFB <VAL>
		%OUT EZ_ASM Error #3: MACNAME - `VAR_NAME': Missing initialization
		ENDIF
	IF (.$IN_FCN_MACRO EQ ._YES)
		%OUT EZ_ASM Error #9: MACNAME - `VAR_NAME': Must not be inside START_FCN/END_FCN pair
		ENDIF		
     ENDM


STATIC MACRO  DATA_TYPE, VAR_NAME, VAL, ERR_VAL;
		                                           
	IF1
		.$DARG_CHK STATIC, VAR_NAME, <VAL>, <ERR_VAL>
		ENDIF
	
	START_DATA
	.$DEFINE_DATA_ITEM STATIC, DATA_TYPE, <VAR_NAME>, <VAL>
	END_DATA

	IF (DATA_TYPE NE CODE_PTR)
		.ID&VAR_NAME = .xSTATIC + (DATA_TYPE AND 0FH)
		ENDIF
		
	ENDM
	


.$DEFINE_DATA_ITEM MACRO MAC_NAME, DATA_TYPE, VAR_NAME, VAL
	
	IF (DATA_TYPE AND ._FCN_PTR)
		.$SET_FCN_DECL .$STATIC_FCN, VAL, DATA_TYPE, VAR_NAME
	     EXITM
	     ENDIF
	     
	IF (DATA_TYPE EQ CHAR)   
		VAR_NAME DB	VAL;
		EXITM
		ENDIF
		
	IF (DATA_TYPE EQ STRING)   
		VAR_NAME DB	VAL, 0
		EXITM
		ENDIF
		
	IF ((DATA_TYPE EQ _INT) OR (DATA_TYPE EQ ._SMALL_DATA_PTR))
		VAR_NAME DW	VAL;
		EXITM
		ENDIF              
	
	IF ((DATA_TYPE EQ LONG) OR (DATA_TYPE EQ ._LARGE_DATA_PTR))
		VAR_NAME DD	VAL;
		EXITM
		ENDIF
	
	IF1
		%OUT EZ_ASM Error #2: MAC_NAME - `VAR_NAME': Unknown data type
		ENDIF
	
	ENDM


.$LATTICE_P_MODEL = ._NO
.$IN_AUTO = ._NO
.$IN_FCN_MACRO = ._NO

START_FCN  MACRO  FCN_DECL, FCN_ARGS, ERR_ARG;
	
	IF1
		IF (.$MODULE_IS_DEFINED EQ ._NO)
			%OUT EZ_ASM Error #1: DEFINE_MODULE Macro is missing
			ENDIF
		
		IF (.$IN_FCN_MACRO EQ ._YES)
	     	%OUT EZ_ASM Error #5: START_FCN - `FCN_DECL': Previous END_FCN is missing
		     ENDIF
		
		IFNB <ERR_ARG>
			%OUT EZ_ASM Error #4: START_FCN - `FCN_DECL': Missing < >s around arguments 
	     	ENDIF
		ENDIF
	
	.$SET_FCN_DECL .$START_FCN_CODE, , 0, FCN_DECL
    	
    	.$N_FCN_ARG_BYTES = 0;
    	.$N_AUTO_BYTES = 0;
    	.$N_STACK_BYTES = 0;
	.$AUTO_ARG_BASE = 0;
	.$NEW_STACK_FRAME = ._NO
	.$BP_EQUALS_SP = ._YES;
    	.$FAR_DS = ._NO
	.$IN_FCN_MACRO = ._YES;
	.$PROLOGUE = ._NO;

		.$SETTING_FCN_ARGS = ._YES;
		IF ((.$FCN_CALL_STYLE AND .xC_ARGS) NE 0)
			IRP arg, <FCN_ARGS>
				.$SET_FCN_ARG arg
				ENDM
	     ELSE

     .@N_ARGS = 0						;; Count number of args in list
	IRP ARG, <FCN_ARGS>
     	.@N_ARGS =  .@N_ARGS + 1
          ENDM
	.@N = .@N_ARGS
	REPT .@N_ARGS
		.@COUNT = 1
		IRP ARG, <FCN_ARGS>
			IF (.@COUNT EQ .@N)
			     .$SET_FCN_ARG ARG		;; execute desired macro with arg
				ENDIF
			.@COUNT = .@COUNT+1
			ENDM
		.@N = .@N - 1           
		ENDM

			ENDIF
		.$N_FCN_ARG_BYTES = .$N_STACK_BYTES;
		.$SETTING_FCN_ARGS = ._NO;
	
	.$POP_N_BYTES_ON_RETURN = 0;
	IF ((.$FCN_CALL_STYLE AND .xPOP_ARGS) NE 0)
	     .$POP_N_BYTES_ON_RETURN = .$N_FCN_ARG_BYTES;
		ENDIF
	
	.$ISSUE_PROLOGUE_ERR_MSG MACRO ERR_N
		IF (ERR_N EQ 7)
			%OUT EZ_ASM Error #6: Missing PROLOGUE for `FCN_DECL'
			ENDIF
		IF (ERR_N EQ 5)
			%OUT EZ_ASM Error #4: PROLOGUE - `FCN_DECL': Missing < >s for register list
			ENDIF
	     IF (ERR_N EQ 9)
	     	%OUT EZ_ASM Error #7: AUTO - `FCN_DECL': Must precede PROLOGUE
	     	ENDIF
		ENDM
	
     
     ENDM


.$SET_FCN_DECL MACRO FCN_VEC, VAL, DATA_TYPE, ARG1, ARG2, ARG3, ARG4
	
	IFB <ARG2>
		FCN_VEC DATA_TYPE, ARG1, 0, <VAL>
		EXITM
		ENDIF
		
	IFB <ARG3>
		FCN_VEC DATA_TYPE, ARG2, %.?&ARG1, <VAL>
		EXITM
		ENDIF
	
	IFB <ARG4>
	     FCN_VEC DATA_TYPE, ARG3, %(.?&ARG1 + .?&ARG2), <VAL>
	ELSE		
	     FCN_VEC DATA_TYPE, ARG4, %(.?&ARG1 + .?&ARG2 + .?&ARG3), <VAL>
		ENDIF  
	ENDM	


.$START_FCN_CODE MACRO XXXX, FCN_NAME, FORCE

    	.@FCN_ATTR = .$$DFLT_CODE_ATTR
     
     IF (FORCE NE 0)
          .$SET_FORCE_ATTR FORCE, .@FCN_ATTR
     	ENDIF
	
	.$FCN_CALL_STYLE = .@FCN_ATTR AND .?CP
	
	IF (((FORCE AND .?PASCAL) EQ .?PASCAL) OR (.$$UNDERSCORE EQ ._NONE))
	     .$HEADER_TRAILER_CODE FCN_NAME, .@FCN_ATTR, FCN_NAME
	ELSE
		IF (.$$UNDERSCORE EQ ._LEADING)
		     .$HEADER_TRAILER_CODE _&FCN_NAME, .@FCN_ATTR, FCN_NAME
		ELSE
		     .$HEADER_TRAILER_CODE FCN_NAME&_, .@FCN_ATTR, FCN_NAME
		     ENDIF
	    	
	    	IF ((.@FCN_ATTR AND .xC_ARGS) GT 0)
    			.$C_NAMES		FCN_NAME
    			ENDIF
		
		ENDIF


	.$FCN_ARG_ERR MACRO MAC_NAME
		%OUT EZ_ASM Error #2: MAC_NAME - `FCN_NAME': Unknown data type
		ENDM
	
	ENDM


.$HEADER_TRAILER_CODE MACRO FCN_NAME, FORCE, BARE_NAME
	
	.ID&BARE_NAME = FORCE

	START_CODE 
	
	IF ((FORCE AND .xSTATIC) NE .xSTATIC)
		PUBLIC FCN_NAME
		ENDIF
	IF ((FORCE AND .xFAR) EQ ._NO)
		FCN_NAME PROC NEAR
		.$FCN_RETURN_PTR_SZ = ._NEAR_PTR;
	ELSE
		FCN_NAME PROC FAR
	     .$FCN_RETURN_PTR_SZ = ._FAR_PTR;
		IF ((FORCE AND .?FAR) EQ .?FAR) 
		     .$FAR_DS = .$RDS
			ENDIF
		ENDIF

	.$END_FCN_CODE MACRO MISSING_PROLOGUE
			
		FCN_NAME ENDP
		END_CODE
			
		ENDM
	
	ENDM
	
	
.$SET_FCN_ARG MACRO DATA_TYPE, ARG_NAME
	LOCAL .@FRAME_PTR, .@N_BYTES

	.@N_BYTES = &DATA_TYPE AND 0FH
	
	.ID&ARG_NAME	=	.xSTACK + .@N_BYTES
	
	IF (.@N_BYTES EQ CHAR)
		.@N_BYTES = _INT
		ENDIF	
	
	IF1
		IF ((.@N_BYTES NE _INT) AND (.@N_BYTES NE LONG) AND (.@N_BYTES NE DOUBLE))
		     IF (.$IN_AUTO EQ ._NO)
		     	.$FCN_ARG_ERR START_FCN
			ELSE
		     	.$FCN_ARG_ERR AUTO
				ENDIF
			ENDIF
		ENDIF

	IF (.$SETTING_FCN_ARGS EQ ._YES)
	    	.@FRAME_PTR = .$N_STACK_BYTES
		ARG_NAME EQU	         .$FCN_ARG_BASE+.@FRAME_PTR[BP]
	ELSE
	     .@FRAME_PTR = -(.$N_STACK_BYTES + .@N_BYTES);
		ARG_NAME EQU	         .$AUTO_ARG_BASE+.@FRAME_PTR[BP]
	     ENDIF
	
	.$N_STACK_BYTES = .$N_STACK_BYTES + .@N_BYTES
	                   
	ENDM


PROLOGUE MACRO REG_LIST, ERR_ARG
	
	._START_REGS = 0FFFFH - (.$RSI+.$RDI+.$RES) + (.$$SAVE_SI+.$$SAVE_DI+.$$SAVE_ES)

	IF1
		IFNB <ERR_ARG>
		     .$ISSUE_PROLOGUE_ERR_MSG 5
		     ENDIF
		IF (.$IN_FCN_MACRO EQ ._NO)
			%OUT EZ_ASM Error #8: PROLOGUE must be inside a START_FCN/END_FCN pair
			ENDIF              
		
		ENDIF
	
	.$PROLOGUE = ._YES;
    	.$PUSH_N_REGS = 0;
	 
	IF ((.$$RESET_DS + .$FAR_DS) EQ 0)
	     .$SAVE_REGISTERS = ._START_REGS
	ELSE
	     PUSH	DS
	     MOV	AX, DS_LBL
	     MOV	DS, AX
	     .$FAR_DS = .$RDS
	     .$SAVE_REGISTERS = ._START_REGS - .$RDS
		ENDIF

	.$$SET_FCN_STACK_FRAME <REG_LIST>
	
	.$POP_PROLOGUE_REGS MACRO
		.$REV_ORDER .$POP_REGS <REG_LIST>
		ENDM

	.$POP_REGS MACRO REGISTER
    		.$CHK_REG %(.$R&&REGISTER)
    		IF (.$SV_REG NE 0)
			IF (.$SV_REG NE .$RF_ES)
				POP	REGISTER
		    	ELSE
		    		.$FORCE_REG POP, %(.$P&&REGISTER)
		    		ENDIF
			ENDIF
		ENDM

	ENDM     
	

.$PUSH_PROLOGUE_REGS MACRO REG_LIST
	IRP	REG, <REG_LIST>
    		.$CHK_REG %(.$R&&REG)
    		IF (.$SV_REG NE 0)
			IF (.$SV_REG NE .$RF_ES)
				PUSH	REG
		    	ELSE
		    		.$FORCE_REG PUSH, %(.$P&&REG)
		    		ENDIF
		    	.$PUSH_N_REGS = .$PUSH_N_REGS + 1;
			ENDIF
		ENDM
 	ENDM
 	

.$FORCE_REG  MACRO  CMND, REG
	IF (REG EQ .$RSI)
		CMND		SI
		ENDIF
	IF (REG EQ .$RDI)
		CMND		DI
		ENDIF
	IF (REG EQ .$RES)
		CMND		ES
		ENDIF
	ENDM


.$CHK_REG MACRO REG, REG_MASK
     .$SV_REG = REG AND .$SAVE_REGISTERS
	ENDM


INT_RET	= 1
NO_RET	= 2

END_FCN  MACRO RET_FROM_FUNC
	
	IF (.$PROLOGUE EQ ._YES) 
		.$POP_PROLOGUE_REGS           	; .$$RESET_FCN_STACK_FRAME MACRO
		
		IF (.$N_AUTO_BYTES GT 0)
			IF (.$AUTO_ARG_BASE EQ 0)
				MOV	SP, BP
			ELSE 
				ADD  SP, .$N_AUTO_BYTES + .$N_FCN_ARG_BYTES
				ENDIF
			ENDIF
		
		IF (.$NEW_STACK_FRAME EQ ._YES)
			POP	BP
			ENDIF
	ELSE
		IF1
			IF ((.$N_AUTO_BYTES + .$N_FCN_ARG_BYTES) GT 0)
				.$ISSUE_PROLOGUE_ERR_MSG 7
				ENDIF
			ENDIF
		ENDIF
			
     IF (.$FAR_DS GT 0)
		POP	DS
		ENDIF  
		
	IFB <RET_FROM_FUNC>
		RET	.$POP_N_BYTES_ON_RETURN
	ELSE
		IF (RET_FROM_FUNC EQ INT_RET)
			IRET
			ENDIF
		ENDIF
	
	.$END_FCN_CODE
	
	.$IN_FCN_MACRO = ._NO;
	
	ENDM



AUTO MACRO AUTO_VARIABLES

	IF1 
		IF (.$PROLOGUE EQ ._YES)
			.$ISSUE_PROLOGUE_ERR_MSG 9
			ENDIF
		
		IF (.$IN_FCN_MACRO EQ ._NO)
			%OUT EZ_ASM Error #7: AUTO must be inside a START_FCN/END_FCN pair
			ENDIF
		
		ENDIF
		
	.$IN_AUTO = ._YES
	.$N_STACK_BYTES = 0;
	IRP arg, <AUTO_VARIABLES>
		.$SET_FCN_ARG arg;
		ENDM
	.$N_AUTO_BYTES = .$N_STACK_BYTES;
	.$IN_AUTO = ._NO
	
	ENDM
	

.CALL MACRO FCN_NAME, FCN_ARGS, ERR_ARG
	LOCAL .FCN_NAME
	
	.$PUSH_N_BYTES = 0;
	.$AX_REGISTER = 0;
	.$IS_FIRST_CONSTANT_TO_BE_PUSHED = ._YES
	
	IF1
		IFNB<ERR_ARG>
			%OUT EZ_ASM Error #4: .CALL - `FCN_NAME': Missing < >s around arguments for FCN_NAME
			ENDIF
		ENDIF

     .$GET_ID_ATTR FCN_NAME
	
	.@FCN_TYPE = .$ID_TYPE
     .@FCN_SEG = .$ID_ATTR AND .xFAR
     .@FCN_SIZE = .$ID_SIZE
     IF (.@FCN_TYPE EQ .xSTACK)
     	.ID&FCN_NAME = .$$DFLT_CODE_ATTR
     	ENDIF
	
	IF ((.ID&FCN_NAME AND .xC_ARGS) GT 0)
		.$REV_ORDER .$PUSH_FCN_ARG, <FCN_ARGS>
	ELSE
		IRP ARG, <FCN_ARGS>
			.$PUSH_FCN_ARG <ARG>
			ENDM
		ENDIF     

     IF (.@FCN_TYPE NE .xSTACK) 
     	IF (.@FCN_TYPE EQ .xLABEL)
     		IF ((.ID&FCN_NAME AND .xFAR) EQ 0)
     			CALL	NEAR PTR FCN_NAME
     		ELSE
     			CALL FAR PTR FCN_NAME
     			ENDIF
		ELSE
	          .$SET_STATIC_NAME .FCN_NAME, FCN_NAME
	     	IF (.$LATTICE_P_MODEL EQ ._NO)
	     		CALL .FCN_NAME
	     	ELSE
	     		MOV	BX, WORD PTR DS_LBL:FCN_NAME
	     	     IF ((.ID&FCN_NAME AND .xFAR) EQ 0)
	     		     CALL	WORD PTR [BX]
	     		ELSE
	     			CALL	DWORD PTR [BX]
	               	ENDIF
	               ENDIF
			ENDIF
	ELSE
		IF (.@FCN_SIZE NE LONG)
			IF (.$LATTICE_P_MODEL EQ ._NO)
				CALL WORD PTR FCN_NAME
			ELSE
				MOV	BX, FCN_NAME
				CALL DWORD PTR [BX]
				ENDIF
		ELSE 
			CALL DWORD PTR FCN_NAME
			ENDIF
	     ENDIF
     
     IF (((.ID&FCN_NAME AND .xPOP_ARGS) EQ ._NO) AND (.$PUSH_N_BYTES GT 0))
	     IF (.$BP_EQUALS_SP EQ ._YES)
	     	MOV	SP, BP
	     ELSE
	     	ADD	SP, .$PUSH_N_BYTES
	     	ENDIF
     	ENDIF
	
	ENDM



.$PUSH_FCN_ARG MACRO ARG
     LOCAL .ARG
     
     .$FORCE_CAST = _INT
     .$SET_STATIC_NAME .ARG, ARG
     .$FORCE_CAST = 0FH
     IF (.$ID_TYPE EQ .xCONSTANT)
     	.$VAL_IS_IN_REG = ._NO;
     	IF (.$IS_FIRST_CONSTANT_TO_BE_PUSHED EQ ._YES)
		     IF (.ARG NE 0)
			     MOV	AX, .ARG
			ELSE
		     	XOR	AX, AX
		     	ENDIF
		     .$IS_FIRST_CONSTANT_TO_BE_PUSHED = ._NO;
     	ELSE	
     		IF (.ARG EQ .$AX_REGISTER)
     			.$VAL_IS_IN_REG = ._YES;
     		ELSE
     			.@DIFF = .ARG - .$AX_REGISTER
     			IF ((.@DIFF LE 2) AND (.@DIFF GE -2))
     				IF (.@DIFF GT 0)
     					REPT	.@DIFF
     						INC	AX
     						ENDM
     				ELSE
     					REPT -.@DIFF
     						DEC AX
     			               ENDM
     			          ENDIF
     			ELSE
				     IF (.ARG NE 0)
					     MOV	AX, .ARG
					ELSE
		     			XOR	AX, AX
		     			ENDIF
     				ENDIF
     			
     			ENDIF
		     ENDIF
	     PUSH	AX
	     .$AX_REGISTER = .ARG;
	     .$PUSH_N_BYTES = .$PUSH_N_BYTES + 2;
	ELSE 
	     .@ARG_SIZE = .$ID_SIZE
	     IF (.@ARG_SIZE EQ CHAR)
	     	.@ARG_SIZE = _INT
	     	ENDIF
	     IF (.$ID_TYPE EQ .xSTACK)
	     	PUSH	ARG
		     IF (.@ARG_SIZE GT _INT)
		     	PUSH	ARG+2
		     	ENDIF
		     IF (.@ARG_SIZE EQ DOUBLE)
		     	PUSH	ARG+4
		     	PUSH	ARG+6
		     	ENDIF
	     ELSE
	     	PUSH	.ARG
		     IF (.@ARG_SIZE GT _INT)
		     	PUSH	.ARG+2
		     	ENDIF
		     IF (.@ARG_SIZE EQ DOUBLE)
		     	PUSH	.ARG+4
		     	PUSH	.ARG+6
		     	ENDIF
			ENDIF	     	
	     
	     .$PUSH_N_BYTES = .$PUSH_N_BYTES + .@ARG_SIZE
	     ENDIF
	ENDM

.$REV_ORDER MACRO EXEC_MACRO, MACRO_ARGS

     .@N_ARGS = 0						;; Count number of args in list
	IRP ARG, <MACRO_ARGS>
     	.@N_ARGS = .@N_ARGS + 1
          ENDM
	.@N = .@N_ARGS
	REPT .@N_ARGS
		.@COUNT = 1
		IRP ARG, <MACRO_ARGS>
			IF (.@COUNT EQ .@N)
				EXEC_MACRO <ARG>		;; execute desired macro with arg
				ENDIF
			.@COUNT = .@COUNT+1
			ENDM
		.@N = .@N - 1           
		ENDM
      ENDM


.PRET MACRO LO_WORD, HI_WORD
	LOCAL .LO_WORD
	
	IF (DATA_PTR EQ ._SMALL_DATA_PTR)
	     .$FORCE_CAST = 2
     	.$SET_STATIC_NAME	.LO_WORD, LO_WORD
     	.$FORCE_CAST = 0FH
          .$$RET_WORD AX, .IDAX, <LO_WORD>, <.LO_WORD>, .$ID_ATTR
	ELSE
		.LRET <LO_WORD>, <HI_WORD>
		ENDIF
	ENDM



.LRET MACRO LO_WORD, HI_WORD
	IF (.$$LATTICE_LONG EQ ._YES)
		.$RET_LONG <LO_WORD>, BX, .IDBX, <HI_WORD>, AX, .IDAX
	ELSE
		.$RET_LONG <LO_WORD>, AX, .IDAX, <HI_WORD>, DX, .IDDX
		ENDIF
	ENDM


.$FORCE_CAST = 0FH

.$RET_LONG	MACRO LO_WORD, LO_REG, LO_REG_ID, HI_WORD, HI_REG, HI_REG_ID
     LOCAL .LO_WORD, .HI_WORD, .$LO_WORD_ID, .$HI_WORD_ID 
     
     .$FORCE_CAST = 2
     .$SET_STATIC_NAME	.LO_WORD, LO_WORD
     .$FORCE_CAST = 0FH
     IF ((.$ID_TYPE EQ .xSTATIC) OR (.$ID_TYPE EQ .xSTACK) OR (.$ID_TYPE EQ .xLABEL))
          .$$RET_WORD LO_REG, 0, <LO_WORD>,   <.LO_WORD>,   .$ID_ATTR
	     .$$RET_WORD HI_REG, 0, <LO_WORD+2>, <.LO_WORD+2>, .$ID_ATTR
	     EXITM
	     ENDIF
     .$LO_WORD_ID = .$ID_ATTR
     .$SET_STATIC_NAME	.HI_WORD, HI_WORD
     .$HI_WORD_ID = .$ID_ATTR
	IF ((.$HI_WORD_ID EQ LO_REG_ID) AND (.$LO_WORD_ID EQ HI_REG_ID))
		XCHG	HI_WORD, LO_WORD
	ELSE
		IF (.$HI_WORD_ID NE LO_REG_ID)
	          .$$RET_WORD LO_REG, LO_REG_ID, LO_WORD, <.LO_WORD>, .$LO_WORD_ID
			ENDIF
	    	.$$RET_WORD HI_REG, HI_REG_ID, HI_WORD, <.HI_WORD>, .$HI_WORD_ID
		IF (.$HI_WORD_ID EQ LO_REG_ID)
			.$$RET_WORD LO_REG, LO_REG_ID, LO_WORD, <.LO_WORD>, .$LO_WORD_ID
			ENDIF
	    	ENDIF
	ENDM


.$$RET_WORD MACRO REG, REG_ID, SRC, .SRC, SRC_ID
	IF (REG_ID NE SRC_ID)
		IF (SRC_ID LE .xREG)
			MOV REG, SRC
	     ELSE
	     	MOV REG, .SRC
	     	ENDIF
		ENDIF
	ENDM


	
.LES	MACRO REG, VAL
	IF ((DATA_PTR EQ ._SMALL_DATA_PTR) AND (.$$SAVE_ES EQ ._NO))
		PUSH DS 
		POP  ES 
		ENDIF
     .$LD_PTR LES, REG, <VAL>
	ENDM


.LDS	MACRO REG, VAL
	.$LD_PTR LDS, REG, <VAL>
	ENDM

.$LD_PTR MACRO INSTRUCTION, REG, VAL
	LOCAL .VAL
	
	.$SET_STATIC_NAME .VAL, VAL
	IF (.$ID_TYPE EQ .xSTACK)
		IF (.$ID_SIZE LT LONG)
			MOV  REG, WORD PTR VAL
		ELSE
			INSTRUCTION REG, DWORD PTR VAL
			ENDIF
	ELSE
		IF (.$ID_SIZE LT LONG)
			MOV  REG, .VAL
		ELSE
			INSTRUCTION REG, .VAL
			ENDIF
		ENDIF
	ENDM


.$ES_EQ_DS = ._NO

.LES@	MACRO	REG, VAR_NAME
	IF (.$$SAVE_ES EQ ._NO)
		PUSH DS 
		POP  ES 
		.$ES_EQ_DS = ._YES
		ENDIF
     .$LD_ADDRESS REG, ES, .IDES, <VAR_NAME>
	.$ES_EQ_DS = ._NO
	ENDM


.LDS@	MACRO	REG, VAR_NAME
	.$LD_ADDRESS REG, DS, .IDDS, <VAR_NAME>
	ENDM
	

.$SET_OFFSET = ._NO

.$LD_ADDRESS MACRO	REG, SEG_REG, SEG_REG_ID, VAR_NAME
	LOCAL .VAR_NAME
	
	.$GET_ID_ATTR VAR_NAME
	IF (.$ID_TYPE EQ .xSTACK)
		LEA	REG, VAR_NAME
		IF (.$$DATA_SIZE EQ ._LARGE_DATA)
			PUSH	SS
			POP	SEG_REG
			ENDIF
	ELSE
		.$SET_OFFSET = SEG_REG_ID
		.$SET_STATIC_NAME .VAR_NAME, VAR_NAME
		.$SET_OFFSET = ._NO
		MOV	REG, OFFSET .VAR_NAME
		IF ((.$ID_ATTR AND .xFAR_EXTERN) EQ 0) AND (SEG_REG_ID EQ .IDES) AND (.$ES_EQ_DS EQ ._NO))
			PUSH	DS
			POP	ES
			ENDIF
		ENDIF
	ENDM

	
.?EQ EQU JE
.?NE EQU JNE
.?GT EQU JG
.?LT EQU JL
.?GE EQU JGE
.?LE EQU JLE
.?AB EQU JA
.?BL EQU JB
.?AE EQU JAE
.?BE EQU JBE

.?BIT_IS_OFF_IN EQU  1
.?BIT_IS_ON_IN  EQU  2


.IF	MACRO ARG1, COND, ARG2, ARG3, LBL 
     .$IF <ARG1>, .?&COND, <ARG2>, <LBL>, %.?&COND
	ENDM

.$IF MACRO ARG1, JMP_COND, ARG2, LABEL, TYPE
	LOCAL .ARG1, .ARG2
	
IF (@MASM_VER GE 60)
	IFIDNI <JMP_COND>, <.?BIT_IS_ON_IN>
		XTYPE = TYPE
	ELSEIFIDNI <JMP_COND>, <.?BIT_IS_OFF_IN>
		XTYPE = TYPE
	ELSE
		XTYPE = 0
	ENDIF
ELSE
	IF ((.TYPE TYPE) AND 20H) EQ 0)
		XTYPE = 0
	ELSE
	     XTYPE = TYPE
		ENDIF
ENDIF
	IF (XTYPE NE 0)
	     .$SET_STATIC_NAME .ARG2, ARG2
		IF (.$ID_TYPE EQ .xSTACK)
			TEST .ARG2 ARG2, ARG1
		ELSE
			TEST	.ARG2, ARG1
			ENDIF                       
	     IF (XTYPE EQ 1)
	     	JZ	LABEL
	     ELSE 
	          JNZ	LABEL
	          ENDIF
	ELSE		
		.$SET_STATIC_NAME .ARG1, ARG1
		IF (.$ID_TYPE EQ .xSTACK)
		     CMP	.ARG1 ARG1, ARG2
		ELSE
			CMP	.ARG1, ARG2
			ENDIF                       
		JMP_COND LABEL
		ENDIF
	ENDM
 

.SHR MACRO VAR, SHIFT_N_BITS
	.$SHIFT_BITS SHR, <VAR>, SHIFT_N_BITS
     ENDM

.SHL MACRO VAR, SHIFT_N_BITS
	.$SHIFT_BITS SHL, <VAR>, SHIFT_N_BITS
     ENDM

.SAR MACRO VAR, SHIFT_N_BITS
	.$SHIFT_BITS SAR, <VAR>, SHIFT_N_BITS
     ENDM

.SAL MACRO VAR, SHIFT_N_BITS
	.$SHIFT_BITS SAL, <VAR>, SHIFT_N_BITS
     ENDM

.ROL MACRO VAR, SHIFT_N_BITS
	.$SHIFT_BITS ROL, <VAR>, SHIFT_N_BITS
     ENDM

.ROR MACRO VAR, SHIFT_N_BITS
	.$SHIFT_BITS ROR, <VAR>, SHIFT_N_BITS
     ENDM

.RCL MACRO VAR, SHIFT_N_BITS
	.$SHIFT_BITS RCL, <VAR>, SHIFT_N_BITS
     ENDM

.RCR MACRO VAR, SHIFT_N_BITS
	.$SHIFT_BITS RCR, <VAR>, SHIFT_N_BITS
     ENDM 


.CL EQU	194

.$SHIFT_BITS MACRO INSTRUCTION, VAR_NAME, SHIFT_N_BITS
	LOCAL .CAST_NAME, SHIFT_BITS

     .@REP_N = 1
     .$SET_STATIC_NAME .CAST_NAME, VAR_NAME
 	IF (SHIFT_N_BITS EQ .CL)
 		SHIFT_BITS EQU CL
 	ELSE
		IF (.$$USE_286_INSTRUCTION_SET EQ ._NO)
	  		.@REP_N = SHIFT_N_BITS
	  		SHIFT_BITS EQU 1
	      ELSE
	          SHIFT_BITS EQU SHIFT_N_BITS
	      	ENDIF
	      ENDIF
	REPT .@REP_N
		IF (.$ID_TYPE LE .xREG)
			IF (.$ID_TYPE EQ .xREG)
				INSTRUCTION VAR_NAME, SHIFT_BITS
			ELSE
				INSTRUCTION .CAST_NAME VAR_NAME, SHIFT_BITS
				ENDIF
		ELSE
			INSTRUCTION .CAST_NAME, SHIFT_BITS
			ENDIF
		ENDM
	ENDM

.LSMOV MACRO DEST_OP, SRC_OP 
     IF (.$$DATA_SIZE EQ ._LARGE_DATA)
     	.SMOV <DEST_OP>, <SRC_OP>
     	ENDIF
	ENDM

.SMOV MACRO DEST_OP, SRC_OP 
     .SDO MOV, <DEST_OP>, <SRC_OP>
	ENDM

.SCMP MACRO DEST_OP, SRC_OP 
     .SDO CMP, <DEST_OP>, <SRC_OP>
	ENDM

.SADD MACRO DEST_OP, SRC_OP 
     .SDO ADD, <DEST_OP>, <SRC_OP>
	ENDM

.SSUB MACRO DEST_OP, SRC_OP
     .SDO SUB, <DEST_OP>, <SRC_OP>
	ENDM

.SDEC MACRO DEST_OP 
     .SDO DEC, <DEST_OP>
	ENDM

.SINC MACRO DEST_OP 
     .SDO INC, <DEST_OP>
	ENDM


.$RESET_ES = 0

.SDO MACRO ASM_INS, DEST_OP, SRC_OP 
	LOCAL .DEST_OP, .SRC_OP
	
	.$RESET_ES = 10
	.$SET_STATIC_NAME .DEST_OP, DEST_OP
	IFNB <SRC_OP>
		IF (.$ID_TYPE EQ .xSTATIC)
		     ASM_INS .DEST_OP, SRC_OP
		ELSE
			.$SET_STATIC_NAME .SRC_OP, SRC_OP
		     ASM_INS DEST_OP, .SRC_OP 
			ENDIF
	ELSE
	     ASM_INS .DEST_OP
		ENDIF
	
	IF (.$RESET_ES EQ 1)
		POP	ES
		ENDIF
	.$RESET_ES = 0
	
	ENDM



.$SET_STATIC_NAME MACRO OP, NAME1, NAME2, NAME3
	.$GET_ID_ATTR NAME1
	IF (.$ID_ATTR EQ .IDES)
		.$RESET_ES = 0
		ENDIF
     IF ((.$ID_ATTR GT 16) AND (.$ID_TYPE NE .xRPTR))
     	IF (.$SET_OFFSET EQ ._NO)
     		.$SET_STATIC_PTR_NAME OP, NAME1, NAME2
     	ELSE
     	     .$SET_STATIC_ADRESS OP, NAME1, NAME2
     		ENDIF
	ELSE
		IF (.$ID_TYPE NE .xRPTR)
			.@DATA_SIZE = .$ID_SIZE
			.$GET_ID_ATTR NAME2 
			.$ID_ATTR = (.$ID_ATTR AND 0FFF0H) + .@DATA_SIZE
			.$ID_SIZE = .@DATA_SIZE
			ENDIF
     	IF (.$SET_OFFSET EQ ._NO)
			.$SET_STATIC_PTR_NAME OP, NAME2, NAME3 
     	ELSE
			.$SET_STATIC_ADRESS OP, NAME2, NAME3 
			ENDIF
		ENDIF
	ENDM 
	

.$SET_STATIC_PTR_NAME MACRO OP, VAR_NAME, INDEX	
	LOCAL CAST
     
	IF (.$ID_TYPE LE .xCONSTANT)
		IF (.$ID_TYPE EQ .xSTACK)
			.$CAST OP
		ELSE
			IF ((.$ID_TYPE EQ .xRPTR) AND (.$ID_SIZE GT 0))
			    	.$CAST CAST
				OP EQU CAST VAR_NAME
			ELSE
				OP EQU VAR_NAME
				ENDIF
			ENDIF
	ELSE
    		.$CAST CAST
    	     IF (.$ID_ATTR AND .xFAR)
			IF (.$RESET_ES EQ 10)
				.$RESET_ES = 1
				PUSH	ES
				ENDIF
     		MOV	ES, .$SEG&VAR_NAME
     		OP EQU CAST ES:VAR_NAME&INDEX
     	ELSE
     		OP EQU CAST DS_LBL:VAR_NAME&INDEX
     		ENDIF
		ENDIF
	ENDM


.$SET_STATIC_ADRESS MACRO OP, VAR_NAME, INDEX	
	IF (.$ID_TYPE EQ .xSTATIC)
		IF ((.$ID_ATTR AND .xFAR_EXTERN) EQ .xFAR_EXTERN)
			OP	EQU	VAR_NAME&INDEX
     		IF (.$SET_OFFSET EQ .IDES)
				IF (.$RESET_ES EQ 10)
					.$RESET_ES = 1
					PUSH	ES
					ENDIF
     			MOV	ES, .$SEG&VAR_NAME
     		ELSE
     			MOV	DS, .$SEG&VAR_NAME
     			ENDIF
	     ELSE
	     	IF (.$ID_TYPE EQ CS_STATIC)
	     	     OP	EQU	CS_LBL:VAR_NAME&INDEX
	     	ELSE
	     		OP	EQU	DS_LBL:VAR_NAME&INDEX
	     		ENDIF
	     	ENDIF
	     ENDIF
	ENDM


.$CAST MACRO CAST
     IF (.$FORCE_CAST LT 0FH)
    		.@TYPE = .$FORCE_CAST
     ELSE
     	.@TYPE = .$ID_SIZE
     	ENDIF
     IF (.@TYPE EQ _INT)
     	CAST EQU WORD PTR
     	EXITM
     	ENDIF
	IF (.@TYPE EQ CHAR)
		CAST EQU BYTE PTR
	     EXITM
	     ENDIF
	IF (.@TYPE EQ LONG)
		CAST EQU DWORD PTR
		ENDIF
	ENDM


.$GET_ID_ATTR MACRO VARIABLE
	.$$GET_ID_ATTR %.ID&VARIABLE
	ENDM

.$$GET_ID_ATTR MACRO ID_VALUE
	.$ID_ATTR = ID_VALUE
	.$ID_TYPE = ID_VALUE AND .xDATA_TYPE
	.$ID_SIZE = ID_VALUE AND .xDATA_SIZE
	ENDM


.$SET_FORCE_ATTR MACRO FORCE_ATTR, NEW_ATTR    	
    	
    	IF ((FORCE_ATTR AND .?STATIC) NE 0)
    		NEW_ATTR = NEW_ATTR OR .xSTATIC
    		ENDIF
    	IF ((FORCE_ATTR AND .?NEAR) NE 0)
         	NEW_ATTR = NEW_ATTR AND (NOT .xFAR)
    		ENDIF
    	IF ((FORCE_ATTR AND .?FAR) NE 0)
    	     NEW_ATTR = NEW_ATTR OR .xFAR
    	     ENDIF
    	IF ((FORCE_ATTR AND .?CP) NE 0)
    	     NEW_ATTR = (NEW_ATTR AND NOT .?CP) OR (FORCE_ATTR AND .?CP)
    		ENDIF
    	IF ((FORCE_ATTR AND .?PASCAL) NE 0)
    	     NEW_ATTR = FORCE_ATTR OR .?PASCAL
    		ENDIF
	
	ENDM
