C--

From OSDev.wiki
Jump to navigation Jump to search

C--

(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.

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;
  • the code can be either low level (assembly-like), medium level (C like) or very easily mixed;
  • very good (because of the structured form) for writing small toy programs which are close to the hardware;
  • 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;
  • 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 used for x86-related parts of an operating system, but doesn't give as much control as assembly and requires to have both C (or C++) and C-- compilers;

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

?include "nosys.inc"
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;
    byte x;
    word y;
    dword z;
    #define THIS_A_DEFINITION 123
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
}
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;
}
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
  }

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;
 BX = #gdtr;
 $ db 0x3e, 0x0f, 0x01, 0x17
 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.

References