/*
 * This file shows extensions to the C language which this compiler suppors
 */
/*
 * This example shows how to define a variable to be at a specific address
 * in memory.  It isn't very useful in general programming but is a simple
 * optimization for specific cases...
 */
_absolute (0x8000) int aa;
void abstest(void)
{
	aa = 77;
}
/*
 * This example shows how to create a function with pascal parameter passing.
 * It will also remove the leading underscore and upper case the name.
 * pascal language parameters are passed in reverse order from the normal
 * C calling convention, and it is the responsibility of the callee to
 * clean up the stack.  This is the win16 calling convention.
 */
void _pascal pascalfunc(int a, int b, int c)
{
	a = 4;
	pascalfunc(1,2,3);
}
/*
 * I think this is standard C.  I support it.
 */
void _cdecl cdeclfunc(void) 
{
  int a;
}
/*
 * This example shows how to create a function with stdcall parameter passing
 * It will also remove the leading underscore from the name, and it is the
 * responsibility of the callee to clean up the stack.  Use this for
 * leaner code... this is the win32 calling convention.
 */
void _stdcall stdcallfunc(int a, int b, int c)
{
	a = 4;	
	stdcallfunc(1,2,3);
}
/*
 * This example shows how to create an interrupt function for installation
 * into the IDT.  Interrupt functions are handled a little differently from
 * normal functions; instead of looking for parameters in a standard
 * stack frame, all registers are pushed on the stack and the stack
 * frame becomes a pointer to the register image on the stack.  This
 * will also force an IRET instruction instead of RET
 *
 * Note that the _interrupt keyword must come first.
 */
_interrupt void intfunc(int edi, int esi, int ebp, int esp,
				int ebx, int edx, int ecx, int eax,
				int eip, int cs, int eflags)
{
	ecx = 4;
}
/*
 * This example shows how to reload DS in an interrupt function.  The
 * compiler assumes that the next selector in the GDT/LDT after the selector
 * in the CS reg is a valid data segment selector
 */
_interrupt _loadds void int1func(int edi, int esi, int ebp, int esp,
				int ebx, int edx, int ecx, int eax,
				int ds, int eip, int cs, int eflags)
{
	ecx = 4;
}
/* This shows how to emit arbitrary data into the code stream
 */
void genfunc(void)
{
	_genbyte(0x44);
}
/*
 * The compiler is capable of inlining certain commonly used functions.
 * If a function has the _intrinsic keyword in front of its prototype
 *  and the compiler knows how to inline the function, the function 
 * will be inlined.  See the documentation for a list of inlineable functions.
 */
int _intrinsic strlen(char *v);
int intrtest(char *v1)
{
	return strlen(v1);
}
/*
 * this example shows how to create a far function call.  It will use a
 * RETF instruction and offset the parameters appropriately.
 *
 * note that far pointers are not supported.
 */
_far int farfunc(int v)
{
	return v;
}
/*
 * This is one way to emit an int function
 */
int traptest(void)
{
  _EAX = 0x03;
	_trap(0x77);
}
/*
 * This is an example of inline assembly.  Two styles are supported,
 * the inline style and the block style.  Numbers in an inline statement
 * must follow the C conventions.
 */
int asmtest(int pp)
{
	asm mov eax,[pp];
  asm {
		cdq;
  	xor eax,edx;
	  add eax,edx;
  }
  return _EAX;
}
/*
 * By default, the compiler aligns data in structures to make best use of
 * speed rather than size.  If you need a smaller size, or are dealing
 * for example with a data structure stored on disk or being transported
 * across a network, it may be useful to turn the padding off.  The
 * packed and unpacked pragmas control the padding
 */
#pragma packed
struct one {
	int a;
	char b;
	int c;
	short d;
} ;
#pragma unpacked
struct two {
	int a;
	char b;
	int c;
	short d;
} ;
void structest(void)
{
	static struct one aa;
	static struct two bb;
	aa.a = 4;
	bb.a = 4;
	aa.b = 5;
	bb.b = 5;
	aa.c = 6;
	bb.c = 6;
	aa.d = 7;
	bb.d = 7;
}
/*
 * The run time libraries maintain a list of functions to call before and
 * after the main() function is called.  Each function has an associated
 * priority for ordering purposes.  These lists are used to do things like
 * create argc and argv[], intialize malloc and file io, and so on.  If
 * necessary functions can be added to the list using the startup and
 * rundown pragmas.
 */
#pragma startup startupfunc 50
void startupfunc(void)
{
}
#pragma rundown rundownfunc 50
void rundownfunc(void)
{
}
/*
 * The following turns register optimizations off
 */
#pragma regopt
/*
 * the following turns register operations on for the CPU main registers,
 * but not FP.
 */
#pragma regopt AD
/*
 * The following generates an object record that causes the linker to include
 * a specified library (not supported for NASM output
 */
#pragma library (mylib.lib)

/*
 * The following causes a function or variable to have one name in the
 * source file and another name in the output file (alias)
 *
 * Either of the strings can be encapsulated the same way the file names are
 * in a #include statement
 */
#pragma aux <myfunc> = "zz"

void myfunc(void)
{
	myfunc();
}
void main(void)
{
	printf("this program doesn't do anything,\n"
				 "it is meant as an example of compiler features\n"
				 "read the source\n");
}