Copyright Peter Cellik (C) 1995. All rights reserved.
Last Updated: 16 May 1995
HTMLized by Toren K. Smith, 4 May 1996
See STAKPROC.DOC for a more detailed description of all stack procedures.
See REGPROC.DOC for a more detailed description of all REG procedures and macros.
See WBHELP.DOC for help on using the C-- Work Bench.
See C--ASM.DOC for help on C-- inline assembly.
Nothing you have experienced before. :-)
Seriously, its sort of like C and kinda like assembly.
Some examples of valid C-- indentifiers are:
_DOG CoW loony12 HowdYBoys_AND_Girls WOW___ xSome examples of invalid C-- indentifiers are:
12bogus /* cannot start an identifier with a numerical digit */ wowisthisalongidentifieryupitsureisnotOK /* identifier length exceeds 32 */ y_es sir /* spaces not allowed */ the-end /* hyphens not allowed */
The following is a list of C-- reserved identifiers which can not be used as general identifiers for they have already been defined or reserved for other language purposes:
byte word char int dword long fixed32s fixed32u if loop return do while else interrupt void enum inline CARRYFLAG ELSE EXTRACT FALSE FROM IF NOTCARRYFLAG NOTOVERFLOW OVERFLOW TRUE ZEROFLAG NOTZEROFLAG far __CODEPTR__ __DATAPTR__ __POSTPTR__ __COMPILER__ __DATESTR__ __YEAR__ __MONTH__ __DAY__ __HOUR__ __MINUTE__ __SECOND__ __WEEKDAY__ __VER1__ __VER2__ ESBYTE ESWORD ESCHAR ESINT ESDWORD ESLONG ESFIXED32S ESFIXED32U CSBYTE CSWORD CSCHAR CSINT CSDWORD CSLONG CSFIXED32S CSFIXED32U SSBYTE SSWORD SSCHAR SSINT SSDWORD SSLONG SSFIXED32S SSFIXED32U DSBYTE DSWORD DSCHAR DSINT DSDWORD DSLONG DSFIXED32S DSFIXED32U FSBYTE FSWORD FSCHAR FSINT FSDWORD FSLONG FSFIXED32S FSFIXED32U GSBYTE GSWORD GSCHAR GSINT GSDWORD GSLONG GSFIXED32S GSFIXED32U AX CX DX BX SP BP SI DI AL CL DL BL AH CH DH BH ES CS SS DS FS GS HS IS EAX ECX EDX EBX ESP EBP ESI EDI CR0 CR1 CR2 CR3 CR4 CR5 CR6 CR7 DR0 DR1 DR2 DR3 DR4 DR5 DR6 DR7 TR0 TR1 TR2 TR3 TR4 TR5 TR6 TR7This list can be obtained from the C-- compiler at anytime by running it with the /KEYWORDS command line option.
0b11111111 // same as 255
0x00F // same as 15
0o10 // same as 8
Character ConstantsSingle character constants are, like in C, enclosed in single quotes ('). Also as in C, special characters are expressed by a back slash (\) followed by the key letter or letters. Special characters supported are:
'\a' /* same as in C */
'\b' /* beep */
'\f' /* form feed */
'\l' /* line feed */
'\n' /* carrage return */
'\r' /* carrage return */
'\t' /* tab */
'\x??' /* ASCII character formed from the ?? which would be two
hexadecimal digits for the character value */
'\???' /* ASCII character formed from the ??? which would be three
decimal digits for the character value */
Any other character following a back slash is just accepted. This allows
the single quote to be included by '\'', for '' is the NULL character.Multiple character constants are also supported by C--. Some examples of multiple character constants are:
'ab' 'the' 'this is large'There is no limit to the number of characters in a character constant, but only the last 4 characters are significant. This is the maximum that can be stored in a 32 bit variable. For example, 'this is large' would be equivalent to 'arge'.
C-- treats all character constants as a numeric value of the ASCII value of the character. For multiple character constants, the first character is the most significant, thus the value for 'ab' is 'a'*256+'b'.
All numerical values in C-- are integer values.
Some examples of constant expressions are:
45 & 1 + 3 // equals 4 14 - 1 / 2 // equals 6 (remember integer values) 1 * 2 * 3 / 2 + 4 // equals 7
NAME | SIZE | VALUE RANGE | VALUE RANGE |(bytes)| (decimal) | (hex) ---------------------------------------------------------------------------- byte | 1 | 0 to 255 | 0x00 to 0xFF word | 2 | 0 to 65535 | 0x0000 to 0xFFFF dword | 4 | 0 to 4294967295 | 0x00000000 to 0xFFFFFFFF fixed32u | 4 | 0 to 65535.999985 | 0x0000.0000 to 0xFFFF.FFFF char | 1 | -128 to 127 | 0x80 to 0x7F int | 2 | -32768 to 32767 | 0x8000 to 0x7FFF long | 4 | -2147483648 to 2147483647 | 0x80000000 to 0x7FFFFFFF fixed32s | 4 | -32768 to 32767.999985 | 0x8000.0000 to 0x7FFF.FFFFNOTE1: 32 bit (4 byte) integer instructions are used to implement dword, long, fixed32s and fixed32u values, therefore support for these data types is limited to 80386 and higher CPU's.
NOTE2: fixed32s and fixed32u are not fully implemented, and will be available future versions of C--.
Declaration of Global Variables
The syntax for declaring variables is as follows:
variable-type identifier;Where variable-type is any one of char, byte, int, word, long or dword. Several identifers may be declared of the same type as follows:
variable-type identifier1, identifier2, ... , identifierN;One dimensional arrays may be declared as follows:
variable-type identifier[elements];Where elements is a constant expression for the amount of entries of that variable type to be in the array.
Some examples of global declarations:
byte i,j; /* declare i and j to be of type byte */ word see[10] /* declare see to be an array of 10 word's */ int h,x[27] /* declare h to be of type int and declare x to be an array of 27 int's */
There are two types of conditional expressions, simple and complex.
Simple Conditional Expressions
Complex Conditional Expressions
Complex conditional expressions are of the following form:
( leftside compare_op rightside )Where:
'leftside' is any AL/AX/EAX or constant expression. The expression type will be determined by the first token (register or variable)default is 'word', if an other type is desired, the keyword 'byte', 'char', 'int', 'long' or 'dword' can preceed the expression to specify its type. 'compare_op' is any one of '==', '!=', '<>', '<', '>', '<=', or '>='. 'rightside' is any single register, variable or constant expression.Some examples of valid complex conditional expressions:
( x+y > z ) (int CX*DX <= 12*3 ) (byte first*second+hold == cnumber )Some examples of invalid complex conditional expressions:
( x+y >= x-y ) // rightside is not a single token or constant expr. ( z = y ) // '==' not '=' must be used
Types of Procedures, Functions and Macros
word add_them_all (int a,b,c; byte d,e; word x,y)
{
return( a+b+c+d+e+x+y );
}
REG ProceduresREG procedures are defined by using an identifer that does not contain any lower case letters.
As mentioned, the parameters (if any) for a REG procedure are passed via registers. REG procedures have a maximum of 6 parameters. The registers used if the parameters are of type 'int' or 'word', in order, are AX, BX, CX, DX, DI, and SI. The first four parameters can also be of the type 'char' or 'byte', in this case AL, BL, CL and DL are used respectively. Any of the six parameters can be of type 'long' or 'dword', in which case EAX, EBX, ECX, EDX, EDI, or ESI would be used.
An example of a REG procedure named 'TOGETHER' that returns a 'word' value which is the first parameter multiplied to the second parameter, both parameters are 'word's:
word TOGETHER () /* AX = first param, BX = second param */
{
return( AX * BX );
}
An example of a REG procedure named 'SHOW_NUM' that does not return any value
but writes the first parameter (which is an 'int') followed by the second
parameter (which is a 'byte') to the screen separated by a ':':
void SHOW_NUM () /* AX = first number, BL = second number */
{
? PUSH BX
WRITEINT(int AX);
WRITE(':');
? POP BX
WRITEWORD(BL);
}
In order for a REG procedure to be used as a macro, it must be declared as a
dynamic procedure. Dynamic procedures are described in the following
sub-section.Dynamic procedures are specified by a preceding ':'.
: void setvideomode (byte mode)
{
AL = mode;
AH = 0;
$ INT 0x10
}
An example of a dynamic REG procedure (and could be used as a macro):
: int ABS () /* AX = number to get absolute value of */
{
IF(int AX < 0 )
-AX;
}
Return ValuesReturn values from functions are returned via registers, below is a table showing what register is used for each return type:
return type | register returned in ---------------------------------------- byte | AL word | AX dword | EAX char | AL int | AX long | EAXThe easiest way to return a value from a function is to use the 'return()' command, but the appropriate register can also be assigned the required return value instead. For example, the following two functions return the same value:
byte proc_one ()
{
return( 42 );
}
byte proc_two ()
{
AL = 42;
}
Take note, for dynamic REG procedures that you wish to use as macros, the
'return()' command cannot be used, for the 'return()' also executes a 'RET'
command. Thus for macros that are functions, the appropriate return value
register must be assigned directly.
stack_procedure(x,y);is the same as:
stack_procedure(word x,word y);C-- does not remember what the type is for each parameter of a procedure, care must be used by the programmer to ensure that the types are the same. For example, if a procedure has three parameters, and the first parameter is a 'long' and last two are 'int', the programmer must call it in the following format:
stack_procedure(long x,int x,int x);If the programmer left out the 'long', only 6 bytes will be pushed onto the stack, not 8. Unexpected things would then start to happen, so watch out.
REG_PROCEDURE(AX,BX,CX,DX,DI,SI);If byte or char is used in a position, the 8 bit register that is used for the position is as follows (note that byte or char values cannot be used in the DI and SI positions):
REG_PROCEDURE(byte AL,byte BL,byte CL,byte DL);If dword or long is used in a positions, the 32 bit register that will be used for the position is as follows:
REG_PROCEDURE(long EAX,long EBX,long ECX,long EDX,long EDI,long ESI);Macros
Macros are simply REG procedures whose code is inserted rather than called. An '@' symbol is placed before the REG procedure name to specify the code to be inserted rather than called. In order for a REG procedure to be used as a macro, the REG procedure must be declared as a dynamic procedure or found in the internal library.
All other characteristics of macros are identical to REG procedures.
Selection statements, better known as 'if' statements, are similar to those in C. C-- has two selections statements. 'if' and 'IF'. 'if' does a near jump, and 'IF' does a short jump. 'IF' executes faster, and can save up to 3 bytes in code size but can only jump over 127 bytes of code.
Selection statements, like in C can be followed by either a single command, or a block of many commands enclosed within '{' and '}'. C-- selection statements are restricted to C-- conditional expressions (as described in section 1.4 Expressions).
If more than 127 bytes of code follow an 'IF' statement, the compiler will issue the following error message:
IF jump distance too far, use if.This can be simply remeded by changing the offending 'IF' statement to 'if'.
'else' and 'ELSE' statements are used just like the 'else' command in C, except that 'ELSE' has the same 127 byte jump restriction as 'IF' of 127 bytes. 'else' generates 1 more byte of code than 'ELSE'.
'IF' and 'else', and 'if' and 'ELSE' may be mixed freely, such as the following example:
if( x == 2 )
WRITESTR("Two");
ELSE{WRITESTR("not two.");
printmorestuff();
}
If more than 127 bytes of code follow an 'ELSE' statement, the compiler will
issue the following error message:
ELSE jump distance too far, use else.Simply change the 'ELSE' statement to 'else' to correct the error.
C-- has two types of looping statements. They are 'do {} while' and 'loop'.
count = 0;
do {
count++;
WRITEWORD(count);
WRITELN();
} while (count < 5);
The conditional expression in the 'do {} while' statement must conform to the
same rules as 'IF' and 'if' statements. count = 5;
loop( count )
{WRITEWORD(count);
WRITELN();
}
Use of the register CX for small code block loops will yield the greatest
code size efficiency for a 'loop', for the loop will be implemented by the
use of the machine language 'LOOP' command.If the loop counter is zero before starting the 'loop' command, the loop will be executed the maximum number of times for the range of the variable. 256 times for a 8 bit (byte or char) counter, 65536 for a 16 bit (word or int) counter, and 4294967296 for a 32 bit (dword or long) loop counter. For example, the following loop will execute 256 times:
BH = 0;
loop( BH )
{
}
If no loop counter is given, the loop will loop forever. The following
example will write *'s to the screen forever:
loop()
WRITE('*');
The programmer may, if he or she wishes to, use and/or change the value of
the loop counter variable within the loop. For example the following loop
will only execute 3 times:
CX = 1000;
loop( CX )
{
IF( CX > 3 )
CX = 3;
}
variable[index] variable[index+BX+SI] variable[index+BX+DI] variable[index+BP+SI] variable[index+BP+DI] variable[index+SI] variable[index+DI] variable[index+BP] variable[index+BX]Some examples:
To assign 1995 to the third word in an array of words called 'xlocations': xlocations[4] = 1995; To assign 0 to the second long in an array of longs called 'addresses': addresses[4] = 0; To use the variable 'count' as an index for assigning TRUE to an array called 'fast': BX = count; fast[BX] = TRUE;Absolute Addressing
Absolute addressing is also available. The same restrictions on the indexes apply as with relative addressing. The calculated index will be absolute from the segment register specified. Any segment register can be used, DS, CS, SS and ES. On a 80386+, FS and GS can also be used.
The syntax is exactly the same to relative addressing, except that a segment and type specifier is used. The specifiers available are:
// addressing the Data Segment DSBYTE[offset] // address a byte in the DS segment DSWORD[offset] // address a word in the DS segment DSCHAR[offset] // address a char in the DS segment DSINT[offset] // address a int in the DS segment DSDWORD[offset] // address a dword in the DS segment DSLONG[offset] // address a long in the DS segment // addressing the Code Segment CSBYTE[offset] // address a byte in the CS segment CSWORD[offset] // address a word in the CS segment CSCHAR[offset] // address a char in the CS segment CSINT[offset] // address a int in the CS segment CSDWORD[offset] // address a dword in the CS segment CSLONG[offset] // address a long in the CS segment // addressing the Stack Segment SSBYTE[offset] // address a byte in the SS segment SSWORD[offset] // address a word in the SS segment SSCHAR[offset] // address a char in the SS segment SSINT[offset] // address a int in the SS segment SSDWORD[offset] // address a dword in the SS segment SSLONG[offset] // address a long in the SS segment // addressing the Extra Segment ESBYTE[offset] // address a byte in the ES segment ESWORD[offset] // address a word in the ES segment ESCHAR[offset] // address a char in the ES segment ESINT[offset] // address a int in the ES segment ESDWORD[offset] // address a dword in the ES segment ESLONG[offset] // address a long in the ES segment // addressing the Extra Segment 2 (80386+) FSBYTE[offset] // address a byte in the FS segment FSWORD[offset] // address a word in the FS segment FSCHAR[offset] // address a char in the FS segment FSINT[offset] // address a int in the FS segment FSDWORD[offset] // address a dword in the FS segment FSLONG[offset] // address a long in the FS segment // addressing the Extra Segment 3 (80386+) GSBYTE[offset] // address a byte in the GS segment GSWORD[offset] // address a word in the GS segment GSCHAR[offset] // address a char in the GS segment GSINT[offset] // address a int in the GS segment GSDWORD[offset] // address a dword in the GS segment GSLONG[offset] // address a long in the GS segmentSome examples:
To load AL with the byte value at the address 0000:0417 hex: ES = 0x0000; AL = ESBYTE[0x417]; To move a word value from 2233:4455 hex to A000:0002 hex: $PUSH DS DS = 0x2233; ES = 0xA000; ESWORD[0x0002] = DSWORD[0x4455]; $POP DS To store the int variable X + 2 at address FFFF:1234 hex: ES = 0xFFFF; ESINT[0x1234] = X + 2; To store BX in the stack at offset 42: SSWORD[42] = BX;
Jump labels are used for labeling code locations for use with an inline assembly jump command. There are two types of jump labels, global and local. Global labels, as the name suggests, are labels which are 'visible' from anywhere in the program. Local labels are only 'visible' within their own procedure block and will be undefined outside the block.
Labels are defined by a identifier followed by a colon. If the identifier used contains one or more lower case letters, it is a global jump label, otherwise it is a local jump label.
Global jump labels must not be used within dynamic procedures, only local labels may be used. This is important to remember, for dynamic procedures are relocated at compile time, and for the case of a dynamic REG procedures which can actually be in more than one place in the code, by use of the macro command, thus would result in a label representing more than one address.
AX >< BX; // store the value of BX in AX and the value of AX in BX CH >< BL; // swap the values of CH and BL dog >< cat; /* swap the values of the variable dog and the variable cat */ counter >< CX; // swap the values of counter and CXIf a swap is between two 8 bit memory variables, AL will be destroyed. If a swap is between two 16 bit memory variables, AX will be destroyed. If a swap is between 32 bit memory variables, EAX will be destroyed. In all other cases, such as a memory variable and a register, all register values will be preserved.
-AX; // same as 'AX = -AX;' but faster. -tree; // same as 'tree = -tree;' but faster. -BH; // toggle the sign of BH.NOT Operator
C-- supports a quick syntax of doing a logical NOT toggling on a variable, the NOT operator. By placing a '!' infront of a memory variable or register followed by a ';', the value of the memory variable or register will be changed to the logical NOT of its current value. Some examples follow:
!AX; // same as 'AX ^= 0xFFFF;' but faster. !node; // change the value of 'node' to its logical NOT. !CL; // same as 'CL ^= 0xFF' but faster.Special Conditional Expressions
C-- supports six special conditional expressions:
CARRYFLAG NOTCARRYFLAG OVERFLOW NOTOVERFLOW ZEROFLAG NOTZEROFLAGThese can be used in place of any normal conditional expressions. If for example you wish to execute a block of code only if the carry flag is set, then you would use the following code sequence:
IF( CARRYFLAG )
{
// do some stuff here
}
If you wish to continuously execute a block of code until the overflow flag
is set, you would use something like the following section of code:
do {
// do your thing in here
} while( NOTOVERFLOW );
Interrupt ProceduresInterrupt procedures, procedures which are used as handles for interrupts, are defined in the following manner:
interrupt procedure_name ()
{
// put code here
}
Interrupt procedures do not automatically preserve any registers, and no
registers are modified before the interrupt gains control, therefore it is
your responsibility to 'push' and 'pop' registers and load the DS register
with the appropriate value as required. An example of an interrupt handle
that preserves all registers and loads DS follows:
interrupt safe_handle ()
{
$ PUSH DS
$ PUSH ES
$ PUSHA // 80286+ processor required for this machine instruction
DS = CS; // load DS with appropriate value for tiny memory model
/* do your thing here */
$ POPA // 80286+ processor required for this machine instruction
$ POP ES
$ POP DS
}
C-- does not contain a preprocessor. It does however give the user several funtions that are very similar to the functions of the C preprocessor. These are given by compiler directives. All compiler directives begin with a '?'. Below is a list of supported compiler directives and their functions:
? align /* insert byte into program code if currently
at an odd address. */
? aligner (aligner value) /* set value of insert byte. */
? alignword (TRUE or FALSE) /* enable or disable even address alignment
of words and ints, default is TRUE. */
? assumeDSSS (TRUE or FALSE) /* enable or disable assumption of DS == SS
for local and parameter variable
addressing, default is FALSE. */
? beep /* cause the compiler to beep upon reaching this line */
? codesize /* optimize for code size not speed. */
? ctrl_c (TRUE or FALSE ) /* enable or disable ctrl-C ignoring */
? define (identifier) (token) /* define an identifier. */
? DOSrequired (number) /* set the minimum DOS version required:
high byte major number, low byte minor number:
0x0101 for DOS version 1.1
0x0315 for DOS version 3.21
0x0303 for DOS version 3.3
0x0600 for DOS version 6.0
0x0602 for DOS version 6.2
etc. */
? include ("filename") /* include another source file. */
? jumptomain (NONE, SHORT, NEAR or FALSE)
/* set inital jump type to main(), default is NEAR */
? maxerrors (number) /* number of error to find before compiler aborts,
default is 16 */
? parsecommandline (TRUE or FALSE) /* include command line parsing code into
program, default is FALSE */
? pause /* pause compiling until user presses a key. */
? print (number or string) /* displays a string or number to the screen */
? printhex (number) /* displays a number in hexadecimal to the screen */
? randombyte /* insert a random byte into program code */
? resize (TRUE or FALSE) /* resize program memory block upon start up to the
minimum amount required, default is TRUE */
? resizemessage (string) /* message to display before aborting if the
resizing of the program memory block failed. */
? speed /* optimize for speed (default) not code size */
? stack (number) /* specifies the size of the stack in bytes for the
program */
? startaddress (number) /* set initial code start address, default 0x100 */
? use8086 /* restrict code generation to 8088/8086 (default) */
? use8088 /* restrict code generation to 8088/8086 (default) */
? use80186 /* enable 80186 code generation and optimizations */
? use80286 /* enable 80286 code generation and optimizations */
? use80386 /* enable 80386 code generation and optimizations */
? use80486 /* enable 80486 code generation and optimizations */
? use80586 /* enable 80586 code generation and optimizations */
C-- inline assembly supports all of the 8088/8086 assembly codes, plus most of the 80286 and 80386 enhanced instructions. All codes must start with the $ inline assembly specifier. See the file 'C--ASM.DOC' for a complete list of all assembly op codes supported by C--.
I will tell you later, its not really that complicated.
C-- /SYM C:\COMMAND.COM HELLO.C--An output file HELLO.COM will be created.
You can probably think of lots of ways of using this function, such as:
Anyone with a mischievous mind (most people do) can think of some not so nice ways of using this function. The most obvious of which would be the creation of trojan horses. I WOULD LIKE TO POINT OUT THAT THIS IS NOT A CONSTRUCTIVE USE OF C-- AND ANY DESTRUCTIVE USE OF COM FILE SYMBIOSIS IS PROHIBITED. In other words, don't be a jerk.
C-- STACK FRAME for near (default) stack procedures:
ADDRESS ... BP+FFFE second from last byte of local variables BP+FFFF last byte of local variables BP+0000 Saved BP BP+0002 RET address BP+0004 last word of parameter variables BP+0006 second from last word of parameter variables ...C-- STACK FRAME for far stack procedures:
ADDRESS ... BP+FFFE second from last byte of local variables BP+FFFF last byte of local variables BP+0000 Saved BP BP+0002 RETF address (high) BP+0004 RETF address (low) BP+0006 last word of parameter variables BP+0008 second from last word of parameter variables ...C-- STACK FRAME for interrupt procedures:
ADDRESS ... BP+FFFE second from last byte of local variables BP+FFFF last byte of local variables BP+0000 Saved BP BP+0002 Saved Flags BP+0004 RETF address (high) BP+0006 RETF address (low) BP+0008 last word of parameter variables BP+000A second from last word of parameter variables ...
The command line calling format of the C-- compiler is:
C-- [options]Where options are (short forms are enclosed in '()'):
/8086 -- restrict code generation to simple 8086, default (/0) /8088 -- restrict code generation to simple 8086, default (/0) /80286 -- enable 80286 code optimizations (/2) /80386 -- enable 80386 code optimizations (/3) /80486 -- enable 80486 code optimizations (/4) /80586 -- enable 80586 (P5) code optimizations (/5) /80686 -- enable 80686 (P6) code optimizations (/6) /-ALIGN -- disable even word address alignment (/-A) /+ALIGN -- enable even word address alignment, default (/+A) /-ASSUMEDSSS -- disable assumption of DS=SS optimization, default (/-D) /+ASSUMEDSSS -- enable assumption of DS=SS optimization (/+D) /-CTRLC -- do not insert CTRLMany of these command line options can be overridden by compiler directives in the source file.ignoring code, default (/-C) /+CTRLC -- insert CTRL ignoring code (/+C) /EXE -- produce EXE run file, almost available (/E) /HELP -- get a little help, not much (/?) /KEYWORDS -- display list of C-- reserved words /MACRO <name> -- extract macro from internal library /-MAP -- do not generate map file, default (/-M) /+MAP -- generate map file. (/+M) /ME -- display my name and my address /-MAIN -- disable initial jump to main() (/J0) /+MAIN -- set initial jump to main() to be near, default (/J2) /OBJ -- produce OBJ output file /-RESIZE -- do not insert resize program memory block code (/-R) /+RESIZE -- insert resize program memory block code, default (/+R) /-PARSE -- do not insert parse command line code, default (/-P) /+PARSE -- insert parse command line code (/+P) /PROC <name> -- extract procedure from internal library /QUOTE -- display quote of the program (QOTP) /REGPROC <name> -- extract REG-procedure from internal library /+RESIZE -- insert resize memory block code, default (/+R) /S=##### -- set stack size to ##### decimal value /SIZE -- optimize for code size (/OC) /SHORTMAIN -- initial jump to main() short (/J1) /SPEED -- optimize for speed (default) (/OS) /STACK -- activate compile time compiler stack check /SYM <file> -- COM file symbiosis /X -- disable SPHINX C-- header in output file
You may also notice that in VGA.H--, some procedures have been extracted from the interal library but not yet converted back from binary data to C-- code. I'll get around to it, but they should still be useful as they are.
There is now support for the Gravis Ultra Sound by use of the YEA_GUS.EXE sound driver. If anyone has a better way of programming the card, give me a yell. Support for other sound cards would also be nice.
Send me any code or ideas for procedures that you wish to be added, and I will see what I can do. If you do send code, it will definitely make it easier on me, C++, C, C-- or ASM doesn't matter. Also, if you find any errors or possible optimizations to any of the existing procedures, send it to me.
REGISTERS THAT MUST BE PRESERVED
Registers that should be preserved are BP, DI, SI, DS, SS, SP, CS and IP.
BP is used for pointing to local and parameter variables on the stack, and thus must be preserved.
DS points to the data segment and all global variable operations requires its value.
SYMBOL | FUNCTION | EXAMPLE
------------------------------------------------------------------------
/* | start comment block | /* comment */
*/ | end comment block | /* comment */
| |
// | comment to end of line | // comment
| |
= | assignment | AX = 12;
+ | addition | AX = BX + 12;
- | subtraction | house = dog - church;
* | multiplication | x = y * z;
/ | division | x1 = dog / legs;
& | bitwise AND | polution = stupid & pointless;
| | bitwise inclusive OR | yes = i | mabe;
^ | bitwise exclusive OR | snap = got ^ power;
<< | bit shift left | x = y << z;
>> | bit shift right | x = y >> z;
| |
+= | addition | fox += 12; // fox = fox +12;
-= | subtraction | cow -= BX; // cow = cow - BX;
&= | bitwise AND | p &= q; // p = p & q;
|= | bitwise inclusive OR | p |= z; // p = p | z;
^= | bitwise exclusive OR | u ^= s; // u = u ^ s;
<<= | bit shift left | x <<= z; // x = x << z
>>= | bit shift right | x >>= z; // x = x >> z
| |
>< | swap | x >< y; /* exchange values of x and y */
| |
== | equal to | IF(AX == 12)
> | greater than | IF(junk > BOGUS)
< | less than | if( x < y )
>= | greater or equal to | if(AX >= 12)
<= | less than or equal to | IF(BL <= CH)
!= | not equal to | IF(girl != boy)
<> | different than | IF(cat <> dog) /* same function as != */
| |
@ | insert code | @ COLDBOOT(); /* insert COLDBOOT code */
: | dynamic procedure | : functionname () // declare functionname
$ | assembly operation | $ PUSH AX /* push AX onto stack */
# | offset address of | loc = #cow; /* loc = address of cow */
| |
~ | | This symbol is currently unused.
Version # Comments
^^^^^^^^^ ^^^^^^^^
up to 0.187 - Lots of versions, and lots of stuff changed.
0.187a - VGAX.H-- modified.
- VGA.H-- supplemented.
- VGAFILL.H-- added.
0.188 - Fixed two lame compare statement bugs.
- Spiffed up docs a bit more.
- KEYCODES.H-- modified and supplemented.
- VIDEO.H-- modified and supplemented.
- WRITEHEX(word_value) added to WRITE.H--.
- STARS.C-- added.
- DPMI.H-- and DPMI.C-- added.
- ZEROFLAG and NOTZEROFLAG conditional expressions added.
0.189 - Fixed local_var = seg_reg bug.
- Everyone should upgrade at least to this version!
0.189a - Docs spiffed.
- STARS.C-- modified.
- DOS.H-- supplemented.
- COMPLETE.C-- added.
- DPMI.H-- and DPMI.C-- modified.
- DOSWRITESTR() added to DOS.H--.
0.190 - DOSWRITESTRING() deleted from internal library.
- DOS.H-- supplemented.
- DATETIME.C-- added.
- Docs spiffed.
- Colour Scheme 3 added for all you boring people who didn't
like Colour Scheme 1.
- VIDEO.H-- supplemented.
0.190a - FIXPATH.C-- ver 1.1 added (created by Jean-Marc
Lasgouttes).
- Colour Scheme 3 in Work Bench modified just slightly.
- Num Pad bug in Work Bench fixed (now version Beta 0.120).
- Search bug found in Work Bench but not yet fixed.
- Bug found and fixed in TINYDRAW.C-- file selection.
- VCPI.H-- and VCPI.C-- added.
- ENCRYPT.C-- added.
- BOUNCE.C-- modified.
0.191 - Functions returning 32 bit values bug found and fixed.
- 'fixed32u' and 'fixed32s' now reserved and are keywords,
they will be used to define 32bit fixed point (16bit.16bit)
variables in the future.
- Docs spiffed up a little.
- Multiple characters in character constants added. For
example: 'ab'.
0.192 - All previous VESA support in VIDEO.H-- removed.
- A little more work done on 32bit fixed point stuff.
- VESA.H-- and VESA.C-- added.
- Offending line in POW4.C-- removed.
0.192a - WAIT() added to SYSTEM.H--.
- SOUND BLASTER SUPPORT ADDED!!! Thanks to Michael B. Martin
for all the code. The following files have been added:
SB.H--, SBDMA.H--, SBDETECT.C--, SBGETVOL.C--,
SBSETVOL.C--, SB_DMA.C-- and SB_DMA_.C--.
- All procedure list is now categorical.
0.192b - FIXPATH.C-- ver 1.1 replaced with ver 1.2.
- TSR.H-- added.
- KEEP() moved from DOS.H-- to TSR.H--.
- PCX.H-- and PCX.C-- added.
0.192c - Procedures added to VGAX.H--.
0.192d - Example files now sorted into multiple directories.
- VGAXFNT5.H-- and XFONT5.C-- added.
0.193 - Fixed a lame long and dword bug (classic cut and paste
bug).
0.194 - Started work on OBJ file output.
- Logitech Cyberman support added (cool toy).
0.195 - Tuned OBJ file output.
- Modified C-- Work Bench to include OBJ and EXE compiler
output file option (even though EXE is not yet supported
by C--).
0.196 - Gained greater mastery of OBJ file format. Thanks to
everyone who sent me info on OBJ and EXE file formats.
Every piece of information helped, you can never have too
many references!. More work may still have to be done.
0.197 - far keyword added.
- added CLOCK.C-- written by Gerardo Maiorano.
0.198 - OBJ output tested and tuned with Turbo Pascal and Microsoft
C. OBJ's now work fine, but still do not support global
data. Will work on this soon.
- Docs spiffed.
0.198a - Cool FIRE.C-- added.
- OBJ options added to Work Bench (now version 0.123).
0.198b - Same as 0.198a, but a new name was needed to fix upload
error to wuarchive.
0.198c - Work Bench now remembers its video mode (now version
0.124).
0.199 - The following 80486 additions to inline assembly added:
BSWAP, CMPXCHG, INVD, INVLPG, WBINVD and XADD.
- File search criteria in Work Bench changed from *.C-- to
*.?-- (now version 0.125).
- Inline ASM help menu option added to Work Bench (now
version 0.126).
0.200 - STRCAT() and strcat() bugs found by Johan in STRING.H--
are fixed.
- If the first value in a stack or register parameter
expression is a dword variable, long variable, 32 bit reg
or fixed32 variable, the parameter expression will be
assumed to be of that type so long as no override was
given. All other expressions will be assumed to be word
type.
0.201 - $REP alias for $REPZ added.
0.202 - long and dword >< bug fixed.
- Compiler recompiled WITHOUT 286 code option. :-)
0.203 - lower case letters added to 5x5 font in VGAFONT.H-- and
VGAXFNT5.H--
- OBJ setting automatically sets jump to main() to none