project...
Sphinx


Logo by
Michael Sheker


Partially updated
May 31, 2003


Sphinx C-- is a programming language that combines C and assembly language. It runs at the DOS commandline and can generate applications, library files and drivers for 16-bit and 32-bit DOS, 32-bit MS Windows, and MenuetOS, and probably more. In this page I introduce C-- and how it can be used for MenuetOS and Windows.

Why write apps in C--? In a nutshell, C-- has low-level features, placing it somewhere between C and assembly. Sometimes a high-level language such as C can be very frustrating when you want to write code that accesses the underlying hardware architecture, or utilises the architecture for optimum efficiency. For example, I have used a C compiler called MACC to write applications for MenuetOS, and to call a software-interrupt routine, passing parameters via registers, involves first pushing the parameters onto the stack, calling an inline asm routine which transfers them to registers then calls the interrupt -- which is very inefficient. Often a C compiler places frustrating restrictions on in-line assembly code -- for example, MACC will only allow asm code outside a C function. C-- releases you from the straight-jacket, into a world of unfettered coding.

Sphinx C-- was originally developed by a Canadian, Peter Cellik, but he stopped working on the project in 1996. The main person who has continued the project is a Russian person, Michael Sheker, and his website is: http://c--sphinx.narod.ru/indexe.htm
At this site you will find the C-- compiler, Phoenix Workbench (IDE), documentation and many examples.

Peter Cellik's documentation on C-- was last updated in 1996. Michael's documentation is partially translated from Russian to English and much is still in Russian. As I found the translated Russian difficult to read, I decided that myself and everyone would benefit from a nicely written documentation file in English. So, here it is:

Sphinx C-- documentation: http://www.goosee.com/cmm/c--doc.htm

The remainder of this page is in two parts: usage of C-- for MenuetOS, and for MS Windows. Firstly, MenuetOS...

C-- for MenuetOS

MenuetOS is a 32-bit preemptive multitasking multithreaded operating system for 386+ CPUs and IBM-compatible PC architecture, complete desktop GUI, TCP/IP networking, CDROM, keyboard, mouse, sound, video interfaces, realtime I/O, size only 61K bytes. International open source project. Complete with source fits on a floppy disk.
I have a webpage dedicated to MenuetOS:

MenuetOS webpage: http://www.goosee.com/menuetos/

MenuetOS itself is written in assembly language and assembled with FASM or NASM. Applications may also be written in assembly language or a high-level language. The requirement is that the generated file be a flat 32-bit binary file with a small header (this header is provided in the file 'msys.h--' in the following example).

One problem is that some recent documentation is in Russian, and it took me awhile to figure out how to compile an example application for MenuetOS.
It has turned out to be a pleasant surprise, and the same first example that I developed for MACC/FASM compiles to almost half the size with C--, at 280 bytes compared with 429 bytes for the same example compiled with MACC.
I also made the very pleasant discovery that C-- now supports type 'float', that is, floating point. I discovered this by examining Michael's "history" page -- he has an impressive record of consistent work on this project over the years and addition of excellent features. So, this is a very active project, very much a plus point.

My simple example

You can download the complete package from the C-- project home page, but if you just want to see my example application, compile and run it, it's very simple to do.

Here is my first simple example application: cmm1.c--
Here are all the files you need to compile it: cmm1.zip (196K)

The zip file contains 'cmm1.c--', 'c--.exe', 'msys.h--', and 'startup.h--'. The latter file doesn't actually do anything, but the compiler 'c--.exe' needs to refer to it. The file 'msys.h--' has the code for the MenuetOS system calls -- this file is not complete, and a volunteer would be welcome to add the rest of the system interrupts to it. I would like to thank Alexey Sugonyaev who developed this library file, now modified by me, and he gave me some assistance with getting started.

With these four files in the same directory, all you need to do is type this at the DOS prompt:

C:> c-- cmm1

That's it. The output will be 'cmm1.com', rename to just 'cmm' if you like, and copy to the MenuetOS floppy disk and reboot. When you have the MenuetOS desktop, choose
Start -> System -> Prompt
and at the Mash prompt type:
mash> CMM1

Second example

I have also included in the above 'cmm1.zip' file, another simple example 'cpuspeed.c--', that displays the speed of the CPU in MHz.
The source code: cpuspeed.c--

System library file

The file 'msys.h--' has the runfile-header, symbol definitions, structure declarations, and MenuetOS system call definitions.
With regard to the latter, I chose to maintain the exact parameter-passing format as for the registers. For example:
/*
04 = WRITE TEXT TO WINDOW
     ebx [x start]*65536 + [y start]
     ecx text color 0x00RRGGBB
     edx pointer to text beginning
     esi text length
     ret: nothing changed
*/
inline register void sys_write_text(dword EBX, ECX, EDX, ESI){
 EAX = 4;
 $int 0x40;
}
You can see here that the first parameter passes both x and y coordinates, and it would seem "nicer" to redefine the C function so that parameters are passed something like this:
 sys_write_text(xstart,ystart,color,#smsg1,23);
However I decided to keep it very simple for the assembly language programmers who may also want to use C--. Therefore, parameters are passed exactly as per each register.
I have always defined the system calls with the registers in the order as shown above, that is, EBX, ECX, EDX, ESI.
Here are examples how sys_write_text() will be used with my library:
  sys_write_text(8<<16+8,0xFFFFFF,"C-- CPU speed example for MenuetOS",34);
and
  sys_write_text(25<<16+25,0xFFFF80,#smsg1,23);
Always remember that Sphinx C-- evaluates expressions in order from left to right. There is no operator precedence and parentheses are not allowed. For example, "(25<<16)+8" is illegal.

More examples for MenuetOS written in C--:
MeFar file manager for MenuetOS, pre-beta, by Alexey: MEFAR.zip

 
C-- for MS Windows

I have put together a little Win32 GUI application to show how easy it is.

Here is the application source code: win1.c--
Here is a zip file with "win1.c--", "win1.rc", and "star.ico": win1.zip

To get ready to compile, you need those three files in the same directory. You will need to have downloaded Michael Sheker's complete package, which has in it a directory called "win", which has all the header files. You will need to edit the "#includepath" line in "win1.c--" (see my example below) to wherever you have placed that "win" directory.
Almost there ... grab "startup.h--" and put it in the working directory also. Either grab "c--.exe" (the compiler) and put it into the working directory also, or make sure it's in the DOS search path.

To compile, just type at the DOS prompt:
  c-- win1
That's it, you'll get an executable, "win1.exe". The C-- compiler also has an inbuilt resource-compiler and linker.

At the beginning of "win1.c--" (the application source file) you'll see this:
#pragma option w32     //create Windows GUI EXE.
#pragma option J0 //no startup code.
#pragma option dbg //create debug information (separate .tds file).
#pragma option lst //generate listing file.
#pragma option w //enable warning.
#pragma option 3 //386 CPU.

#includepath "c:\progra~2\c--\lib\win"
#include "windef.h--"
#include "winbase.h--" //kernel32.dll
#include "wingdi.h--" //gdi32.dll
#include "winuser.h--" //user32.dll
#include "commctrl.h--" //comctl32.dll
#include "commdlg.h--" //comdlg32.dll
#include "shellapi.h--" //shell32.dll

#pragma option ia //no need "$" or "asm" for inline asm.
#include "win1.rc" //resource file.
The "/ia" option eliminates the need for inline asm code to be prefixed with "$" or "asm" keywords. This means that the entire assembly language instruction set become keywords.

The "/j0" option suppresses the startup code and there is a direct jump to main() when the program executes. This is because I have startup code inside main() itself.
You can comment this out and the compiler will put in its own startup code -- examine the generated file "win1.lst" (listing file) to see the output code.

The "/dbg" creates a file called "win1.tds" and these are symbols that the Borland Turbo Debugger can read. Turbo Debugger is available free from Borland -- see the download link at: http://www.goosee.com/x86/.

If you want to understand more about the structure of my skeleton application, a good book will be most helpful. You need one that introduces C programming for Windows using the Win32 API (Application Programming Interface). You do not want a book that describes Visual Basic or C# or C++ or MFC or any kind of object-oriented approach.
There are various online sites that have introductory tutorials, like this one: http://winprog.org/tutorial/.

My little "win1" skeleton is an excellent starting point for much bigger apps. Have fun!


(c) 2002,2003 Barry Kauler http://www.goosee.com/explorer/