# C--

Sphinx Full C-- language is in between the C language and x86-assembly. It is a very neat computer language and the Sphinx Full C-- compiler allows to produce (and mix) 16 bit and 32 bit code for real and protected modes.

It was originally developed by Peter Cellik in Canada and then has been extended for several years by Michael Sheker in Russia.

## Pros

• compiles very small executables;
• good for writing real mode x86 operating systems;
• good for writing TSR programs for DOS;
• supports many executable formats: COM, EXE, SYS (DOS drivers), ROM-BIOS, Windows PE-Coff, Windows DLL, 32bit DOS flat or DPMI, MenuetOS;
• 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 may have more bugs;
• 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, myArr[ESI]; but myArr[myArr] is not allowed);
• it can not output 64bit code.

Early versions of panaLiX used Sphinx Full C--. The Panalix website is here but there is no Sphinx C-- code currently available.

## 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 = '!';
//
\$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(0xd0);
tepx=AL;
kb_cmd(0xd1);
\$ MOV AL, tepx
\$ OR AL, 2
\$ MOV tepx, AL
kb_write(tepx);
kb_cmd(0xae);
\$ STI
//
ESBYTE[0x1b8005]= 127;
```

```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
}
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 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;
byte fname;
int n1, n2, n3, n4, w5;
byte b1;
byte f;
{
\$ 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.
{"ft_lang_label":"__label__en","ft_lang_prob":0.6404002,"math_prob":0.9888609,"size":5629,"snap":"2021-31-2021-39","text_gpt3_token_len":2032,"char_repetition_ratio":0.09155556,"word_repetition_ratio":0.020887729,"special_character_ratio":0.40007105,"punctuation_ratio":0.20391516,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.955683,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2021-09-22T02:06:57Z\",\"WARC-Record-ID\":\"<urn:uuid:6a920fab-688c-48a7-8fef-d86d733c45b4>\",\"Content-Length\":\"21431\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:fd9594f0-8d1a-422c-b4d3-2bcfb08a195e>\",\"WARC-Concurrent-To\":\"<urn:uuid:a48256e5-96ee-4be4-b368-a9fe0c1e9c87>\",\"WARC-IP-Address\":\"173.255.206.39\",\"WARC-Target-URI\":\"https://wiki.osdev.org/C--\",\"WARC-Payload-Digest\":\"sha1:J4NZASMRI3F7NITECHYWYIAJUT6XLZL2\",\"WARC-Block-Digest\":\"sha1:XSRYMNKVJJUNOC4QZ7CIJ5QRSMLPHV47\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2021/CC-MAIN-2021-39/CC-MAIN-2021-39_segments_1631780057303.94_warc_CC-MAIN-20210922011746-20210922041746-00637.warc.gz\"}"}