C--
From OSDev Wiki
(Redirected from C MinusMinus)
This page is about Sphinx Full C--, not about C--, the portable assembly language.
Sphinx Full C-- language is in between the C language and x86-assembly. It is a very neat computer language and the Shinx Full C-- compiler allows to produce (and mix) 16 bit and 32 bit code for real and protected modes.
Contents |
Pros
- good for writing real mode x86 operating systems;
- good for writing TSR programs for DOS
- good for writing x86-related parts of an operating system in a structured and easily readable and easier debuggable way related to structured languages like C and Pascal;
- very good (because of the structured form) for writing small toy programs which are close to the hardware;
- very good for writing bootsectors in;
- the code can be either low level (assembly-like), medium level (C like) or very easily mixed;
- has almost as good control over all the small details of the output binaries as assembly languages provide, but is much more maintainable thanks to structuring; people develop who develop OSes in pure assembly do not need the high-level structures and portability of C and C++, so this means that for many developers, the lack of these high level structures and portability in C-- may not be an issue;
- relatively easy to port from and to C-with-assembly.
Cons
- not portable; it is very closely tied to the x86 assembly;
- is developed by few developers, the community is small; has less users than gcc so more may have more bugs;
- one compiler implementation availlable and only for one platform (DOS);
- larger projects generally should be written in high-level languages, not low-level like Sphinx Full C--;
- can be mixed with other languages in the project, where C-- is used for x86-related low level parts of the system, but doesn't give as much control as assembly and increases the number of compilers necessary;
- in order to be low-level, many limitations are in place: for example, array subscripts (like in x= myArr[subscript]) are limited to simple expressions (like myArr[10], myArr[ESI]; but myArr[myArr[1]] is not allowed);
- C code with inline assembly is no less powerful and easy to write than C--.
I am not sure on the output formats of the compiler but I fear it provides only flat-binary and dos exes. I don't know if it can output 64bit code.
Early versions of panaLiX used Sphinx Full C--.
Examples
byte x = 0b01001;
word y;
dword z;
#define THIS_A_DEFINITION 123
Take over interrupt
dword old0x21 = {};
interrupt int0x21()
{
$PUSH DS
$PUSH ES
$PUSHA
$PUSH FS
//
DS = CS;
FS = 0xb800;
FSBYTE[1682] = '!';
//
$POP FS
$POPA
$POP ES
$POP DS
}
...
int registerInterrupt0x21()
{
FS = 0;
old0x21 = FSDWORD[0x21 * 4];
FSWORD[0x21 * 4] = #int0x21;
FSWORD[0x21 * 4 + 2] = CS;
Log(3, "0x21 registered", 0);
}
ESBYTE[0x1b8003]= 'z';
//
$ CLI
kb_cmd(0xad);
kb_cmd(0xd0);
kb_read();
tepx=AL;
kb_cmd(0xd1);
$ MOV AL, tepx
$ OR AL, 2
$ MOV tepx, AL
kb_write(tepx);
kb_cmd(0xae);
$ STI
//
ESBYTE[0x1b8005]= 127;
read, write
void PRINTF()
{
BX = 0x0007;
$ PUSH SI
SI = AX;
AH = 0xE;
UP:
$ LODSB
$ CMP AL,0
$ JZ DOWN
$ INT 0x10
$ JMP SHORT UP
DOWN:
$ POP SI
}
void readStr()
int tr;
byte b1; word ln;
{
tr = 0; ln = 0;
do
{
tr = 0;
b1 = wait_key();
if (b1 == 13) tr = 1;
if (scanCd == 14)
{
tr = 2;
if (ln > 0)
{
putch(b1); putch(' '); putch(b1);
ln--;
}
}
if (tr == 0) if (ln < 255) if (b1 >= 32)
{
putch(b1);
BX = ln;
st1[BX] = b1;
ln++;
};
} while (tr <> 1);
BX = ln;
st1[BX] = 0;
}
: void kbrSpeed(byte sped, dly)
{
AH = 3;
AL = 5;
BL = sped; // 0x00 - 0x1f
BH = dly; // 0 - 3
$ INT 0x16
}
Disk IO
byte readDisk(byte drive, head, sector, track, howmany; word segm, offs)
int err;
{
err = 0;
lab1:
$ MOV AH, 0
$ MOV DL, drive
$ INT 0x13
$ MOV AX, segm
$ MOV ES, AX
$ MOV BX, offs
$ MOV DL, drive
$ MOV DH, head
$ MOV CL, sector
$ MOV CH, track
$ MOV AL, howmany
$ MOV AH, 2
$ INT 0x13
AL = 0;
if (CARRYFLAG)
{
err++;
if (err < maxDiskErrors) $jmp lab1;
return(AH);
}
return(0);
}
byte readSector(byte drive; word sector; byte howmany;word segm, offs)
word a, b, c, d;
{
a = sector - 1;
c = a % 36;
d = c % 18;
c = c - d;
c = c / 18;
b = a % 18 + 1;
d = a % 36;
a = a - d;
a = a / 36;
AL = readDisk(drive, c, b, a, howmany, segm,offs);
}
byte readCluster(byte drive; word clnum; byte howmany; word segm, offs)
{
AL = readSector(drive, clnum+32, howmany, segm, offs);
}
int fileCluster(word tstart)
byte fbuf[512];
byte fname[11];
int n1, n2, n3, n4, w5;
byte b1;
byte f[11];
{
$ PUSH AX
$ PUSH BX
$ PUSH CX
$ PUSH SI
lastSize = 0;
w5 = 0;
SI = tstart;
n1 = 11;
loop (n1)
{
$ LODSB
CX = #fname +11 - n1;
BX = CX;
DSBYTE[BX] = AL;
}
$ POP SI
n3 = -1;
n1 = 20;
do
{
n2 = 0;
if (w5 == 0) w5 = - readSector(0, n1, 1, DS, #fbuf);
if (w5 <> 0) n1 = 35;
if (w5 == 0)
do
{
n3 = 0;
n4 = 0;
do
{
AX = 32 * n2 + #fbuf + n3;
BX = AX;
b1 = DSBYTE[BX];
AX = #fname + n3;
BX = AX;
if (DSBYTE[BX] <> b1) n4 = 1;
n3++;
} while (n3 <= 10);
AX = n2 * 32 + #fbuf + 28;
BX = AX;
if (n4 == 0) lastSize = DSDWORD[BX];
AX = n2 * 32 + #fbuf + 26;
BX = AX;
if (n4 == 0) w5=DSWORD[BX];
n2++;
} while (n2 <=15);
n1++;
} while (n1 <= 33);
$ POP CX
$ POP BX
$ POP AX
AX = w5;
}
Enable Protected Mode
...
?code32 false
...
DSWORD[#gdtr] = #gdt_end - #gdt0;
DSWORD[#gdtr] = DSWORD[#gdtr] - 1;
DSDWORD[#gdtr + 2] = START + #gdt0;
//
DSWORD[#idtr] = #idt_end - #idt;
DSWORD[#idtr] = DSWORD[#idtr] - 1;
DSDWORD[#idtr + 2] = START + #idt;
//lgdt bx
BX = #gdtr;
$ db 0x3e, 0x0f, 0x01, 0x17
//lidt bx
BX = #idtr;
$ db 0x3e, 0x0f, 0x01, 0x1f
//
$ MOV EAX, CR0
$ OR AL, 1
$ MOV CR0, EAX
//
jump_pm32:
$ db 0xEA
$ dw 0
$ dw 0x10
}
?code32 TRUE
void _1()
{
do_pm32:
//
$ MOV AX, 0x18
$ MOV DS, AX
$ MOV SS, AX
//
$ MOV AX, 0x08
$ MOV ES, AX
//
@setup_pic(0x20, 0x28);
...
These snippets may seem a bit spaghetti code, but not because of some language defficiency but because I didn't look very far for them snippets.
