Compiler source code listed below are analog of 32-bit TinyContext
and may be compiled with it. To do this all I/O functions must be replaced with it's
32-bit analogs and source code must be compiled to get cross compiler.
This cross compiler may be used to get 64-bit compiler.
Unfortunately, in difference to versions for all other platforms, source coge longer then 1000 lines.
Compiled program must be placed in file with name c.prg, compiled result are saved in file c.
char Text [16384];
word pText;
word nText;
word nLine;
byte Code [16384];
word nCode;
word hFile;
char Heap [ 2048];
word nHeap;
word Name [ 128];
word Cls [ 128];
word Sub [ 128];
word Type [ 128];
word Size [ 128];
word Ofs [ 128];
word nName;
word pData;
word nData;
word Stk [ 128];
word pStk;
char Buff [ 128];
word nBuff;
word open() is
inline 0xB8, 0x02, 0x00, 0x00, 0x00; // mov RAX, 2
inline 0xBF, 0x68, 0x40, 0x05, 0x08; // mov RDI, @@DATA+Ofs(Heap[64])
inline 0xBE, 0x00, 0x00, 0x00, 0x00; // mov RSI, 0
inline 0xBA, 0x00, 0x00, 0x00, 0x00; // mov RDX, 0
inline 0x0F, 0x05; // syscall
end
word create() is
inline 0xB8, 0x02, 0x00, 0x00, 0x00; // mov RAX, 2
inline 0xBF, 0x6E, 0x40, 0x05, 0x08; // mov RDI, @@DATA+Ofs(Heap[70])
inline 0xBE, 0x41, 0x02, 0x00, 0x00; // mov RSI, 241H
inline 0xBA, 0xED, 0x01, 0x00, 0x00; // mov RDX, 1EDH
inline 0x0F, 0x05; // syscall
end
word read() is
inline 0xB8, 0x00, 0x00, 0x00, 0x00; // mov RAX, 0
inline 0xBB, 0x20, 0x40, 0x05, 0x08; // mov RBX, @@DATA+Ofs(hFile)
inline 0x48, 0x8B, 0x3B; // mov RDI, qword [RBX]
inline 0xBE, 0x00, 0xC0, 0x04, 0x08; // mov RSI, @@DATA+Ofs(Text)
inline 0xBA, 0x00, 0x40, 0x00, 0x00; // mov RDX, 16384
inline 0x0F, 0x05; // syscall
end
word write() is
inline 0xB8, 0x01, 0x00, 0x00, 0x00; // mov RAX, 1
inline 0xBB, 0x20, 0x40, 0x05, 0x08; // mov RBX, @@DATA+Ofs(hFile)
inline 0x48, 0x8B, 0x3B; // mov RDI, qword [RBX]
inline 0xBE, 0x18, 0x00, 0x05, 0x08; // mov RSI, @@DATA+Ofs(Code)
inline 0xBB, 0x18, 0x40, 0x05, 0x08; // mov RBX, @@DATA+Ofs(nCode)
inline 0x48, 0x8B, 0x13; // mov RDX, qword [RBX]
inline 0x0F, 0x05; // syscall
end
word close() is
inline 0xB8, 0x03, 0x00, 0x00, 0x00; // mov RAX, 3
inline 0xBB, 0x20, 0x40, 0x05, 0x08; // mov RBX, @@DATA+Ofs(hFile)
inline 0x48, 0x8B, 0x3B; // mov RDI, qword [RBX]
inline 0x0F, 0x05; // syscall
end
word puts() is
inline 0xB8, 0x01, 0x00, 0x00, 0x00; // mov RAX, 1
inline 0xBF, 0x01, 0x00, 0x00, 0x00; // mov RDI, 1
inline 0xBE, 0x50, 0x64, 0x05, 0x08; // mov RSI, @@DATA+Ofs(Buff)
inline 0xBB, 0xD0, 0x64, 0x05, 0x08; // mov RBX, @@DATA+Ofs(nBuff)
inline 0x48, 0x8B, 0x13; // mov RDX, qword [RBX]
inline 0x0F, 0x05; // syscall
end
word halt() is
inline 0xB8, 0x3C, 0x00, 0x00, 0x00; // mov RAX, 3CH
inline 0xBF, 0x01, 0x00, 0x00, 0x00; // mov RDI, 1
inline 0x0F, 0x05; // syscall
end
word Init() is
Heap[ 0]:='0';
Heap[ 1]:='1';
Heap[ 2]:='2';
Heap[ 3]:='3';
Heap[ 4]:='4';
Heap[ 5]:='5';
Heap[ 6]:='6';
Heap[ 7]:='7';
Heap[ 8]:='8';
Heap[ 9]:='9';
Heap[10]:='A';
Heap[11]:='B';
Heap[12]:='C';
Heap[13]:='D';
Heap[14]:='E';
Heap[15]:='F';
Heap[16]:='c';
Heap[17]:='h';
Heap[18]:='a';
Heap[19]:='r';
Heap[20]:= char(0);
Heap[21]:='b';
Heap[22]:='y';
Heap[23]:='t';
Heap[24]:='e';
Heap[25]:= char(0);
Heap[26]:='w';
Heap[27]:='o';
Heap[28]:='r';
Heap[29]:='d';
Heap[30]:= char(0);
Heap[31]:='b';
Heap[32]:='e';
Heap[33]:='g';
Heap[34]:='i';
Heap[35]:='n';
Heap[36]:= char(0);
Heap[37]:='i';
Heap[38]:='f';
Heap[39]:= char(0);
Heap[40]:='w';
Heap[41]:='h';
Heap[42]:='i';
Heap[43]:='l';
Heap[44]:='e';
Heap[45]:= char(0);
Heap[46]:='i';
Heap[47]:='n';
Heap[48]:='l';
Heap[49]:='i';
Heap[50]:='n';
Heap[51]:='e';
Heap[52]:= char(0);
Heap[53]:='r';
Heap[54]:='e';
Heap[55]:='t';
Heap[56]:='u';
Heap[57]:='r';
Heap[58]:='n';
Heap[59]:= char(0);
Heap[60]:='e';
Heap[61]:='n';
Heap[62]:='d';
Heap[63]:= char(0);
Heap[64]:='c';
Heap[65]:='.';
Heap[66]:='p';
Heap[67]:='r';
Heap[68]:='g';
Heap[69]:= char(0);
Heap[70]:='c';
Heap[71]:= char(0);
nHeap :=72;
Name[ 0]:=16;
Cls [ 0]:= 1;
Size[ 0]:= 1;
Name[ 1]:=21;
Cls [ 1]:= 1;
Size[ 1]:= 1;
Name[ 2]:=26;
Cls [ 2]:= 1;
Size[ 2]:= 8;
nName := 3;
pStk := 0;
nCode := 0;
pData := 0x0804C000;
nData := pData;
end
word OpenSrc() is
hFile:=open();
pText:=0;
nText:=0;
nLine:=1;
end
word CloseSrc() is
close();
end
word Push(word V) is
Stk[pStk]:=V;
pStk:=pStk+1;
end
word Pop () is
pStk:=pStk-1;
return Stk[pStk];
end
word Stop() is
CloseSrc();
pStk:=0;
while nLine!=0 do
Push (nLine%10);
nLine:=nLine/10;
end
nBuff:=0;
while pStk!=0 do
Buff[nBuff]:=char(Pop()+48);
nBuff :=nBuff+1;
end
Buff[nBuff] :=char(0x0A);
nBuff :=nBuff+1;
puts();
halt();
end
word val () is
word E:=10;
word I:= 0;
if Buff[0]='0' then
if Buff[1]='x' then
E:=16;
I:= 2;
end
end
word N:=0;
while Buff[I]!=char(0) do
word K:=0;
while Heap[K]!=Buff[I] do
if K=E then
Stop();
end
K:=K+1;
end
N:=E*N;
N:=N+K;
I:=I+1;
end
return N;
end
char Look() is
if pText>=nText then
pText :=0;
nText :=read();
if pText>=nText then
return char(0);
end
end
return Text[pText];
end
char Read() is
char Ch:=Look();
if Ch =char(10) then
nLine :=nLine+1;
end
pText :=pText+1;
return Ch;
end
word isalnum() is
if 'A'<=Look() then
if Look()<='Z' then
return 0;
end
end
if 'a'<=Look() then
if Look()<='z' then
return 0;
end
end
if '0'<=Look() then
if Look()<='9' then
return 0;
end
end
return 1;
end
word Digraph(char C1, char C2) is
if Buff[0]=C1 then
if Look()=C2 then
Buff[1]:=Read();
Buff[2]:=char(0);
end
end
end
char Scan() is
word pBuff:=0;
while pBuff =0 do
word sFlag:=0;
while sFlag =0 do
if Look()!=char( 9) then
if Look()!=char(10) then
if Look()!=char(13) then
if Look()!=char(32) then
sFlag:=1;
end
end
end
end
if sFlag=0 then
Read();
end
end
while isalnum()=0 do
Buff[pBuff]:= Read();
pBuff :=pBuff+1;
end
if pBuff=0 then
Buff[pBuff]:= Read();
pBuff :=pBuff+1;
end
Buff[pBuff] :=char(0);
Digraph('<', '=');
Digraph('!', '=');
Digraph('>', '=');
Digraph(':', '=');
if Buff[0]='/' then
if Look()='/' then
while Look()!=char(10) do
if Read()=char(0) then
Stop();
end
end
pBuff:=0;
end
end
end
end
word Comp(word pHeap) is
word pBuff:=0;
while Buff[pBuff]=Heap[pHeap] do
if Buff[pBuff]=char(0) then
return 0;
end
pHeap:=pHeap+1;
pBuff:=pBuff+1;
end
return 1;
end
word Find(word fFlag) is
word pName:=0;
while pName< nName do
if Comp(Name[pName])=0 then
return pName;
end
pName:=pName+1;
end
if fFlag=0 then
Stop();
end
return pName;
end
byte Emi1(byte B) is
if nCode>=16384 then
Stop();
end
Code[nCode]:=B;
nCode:=nCode+1;
end
word Emi2(word W, word N) is
word P :=0;
while P 0xFFFFFFFF then
EmiP(0xBB); // mov RBX, Ofs
Emi2(Ofs[I], 8);
end
end
word Assign(word I) is
if Size[I]>1 then
Emi1(0x5B); // pop RBX
end
if Size[I]=1 then
LdIX(I);
end
if Size[Type[I]]>1 then
EmiP(0x89); // mov [RBX], RAX
end
if Size[Type[I]]=1 then
Emi1(0x88); // mov [RBX], AL
end
Emi1(0x03);
end
word Expr() is
word eFlag:=0;
//if eFlag =0 then
if '0'<=Buff[0] then
if Buff[0]<='9' then
word W:=val();
if W<=0xFFFFFFFF then
Emi1(0xB8); // mov RAX, Val
Emi2(val(), 4);
end
if W> 0xFFFFFFFF then
EmiP(0xB8); // mov RAX, Val
Emi2(val(), 8);
end
eFlag:=1;
end
end
if Buff[0]=''' then
Emi1(0xB8); // mov RAX, Val
Emi2(word(Read()), 4);
Read();
eFlag:=1;
end
if Buff[0]='(' then
Scan();
Expr();
eFlag:=1;
end
//end
if eFlag =0 then
word I:=Find(0);
if Cls[I]=1 then
Push(I);
Scan(); // (
Scan();
Expr();
I:=Pop();
end
if Cls[I]=2 then
if Size[I]>1 then
Push(I);
Scan(); // [
Scan();
Expr();
I:=Pop();
if Size[Type[I]]>1 then
EmiP(0xC1); // shl RAX, 3
Emi1(0xE0);
Emi1(0x03);
end
end
LdIX(I);
if Size[I]>1 then
EmiP(0x03); // add RBX, RAX
Emi1(0xD8);
end
if Size[Type[I]]>1 then
EmiP(0x8B); // mov RAX, [RBX]
Emi1(0x03);
end
if Size[Type[I]]=1 then
EmiP(0x33); // xor RAX, RAX
Emi1(0xC0);
Emi1(0x8A); // mov AL, [RBX]
Emi1(0x03);
end
end
if Cls[I]=3 then
Scan(); // (
Push(I);
Sub[nName]:= 0;
word J:=I+1;
while Sub[J]=1 do
Push(J);
Scan();
Expr();
J:=Pop();
Assign(J);
J:=J+1;
end
I:=Pop();
if J=I+1 then
Scan(); // )
end
word W:=(0xFFFFFFFF-((nCode+5)-Ofs[I]))+1;
Emi1(0xE8); // call Ofs
Emi2(W, 4);
end
end
Scan();
word I:=0;
if Buff[0]='+' then
I:=1;
end
if Buff[0]='-' then
I:=2;
end
if Buff[0]='*' then
I:=3;
end
if Buff[0]='/' then
I:=4;
end
if Buff[0]='%' then
I:=5;
end
if I!=0 then
Emi1(0x50); // push RAX
Push(I);
Scan();
Expr();
I:=Pop();
Emi1(0x5B); // pop RBX
if I =1 then
EmiP(0x03); // add RAX, RBX
Emi1(0xC3);
end
if I =2 then
EmiP(0x93); // xchg RBX, RAX
EmiP(0x2B); // sub RAX, RBX
Emi1(0xC3);
end
if I =3 then
EmiP(0xF7); // mul RBX
Emi1(0xE3);
end
if I>=4 then
EmiP(0x93); // xchg RBX, RAX
EmiP(0x33); // xor RDX, RDX
Emi1(0xD2);
EmiP(0xF7); // div RBX
Emi1(0xF3);
end
if I =5 then
EmiP(0x92); // xchg RDX, RAX
end
end
end
word Cond() is
Scan();
Expr();
word jCode:=0;
if Buff[0]='<' then
jCode:=0x83; // jae Ofs
if Buff[1]='=' then
jCode:=0x87; // ja Ofs
end
end
if Buff[0]='=' then
jCode:=0x85; // jne Ofs
end
if Buff[0]='!' then
jCode:=0x84; // je Ofs
end
if Buff[0]='>' then
jCode:=0x86; // jbe Ofs
if Buff[1]='=' then
jCode:=0x82; // jb Ofs
end
end
if jCode=0 then
Stop();
end
Emi1(0x50); // push RAX
Scan();
Expr();
Emi1(0x5B); // pop RBX
EmiP(0x39); // cmp RBX, RAX
Emi1(0xC3);
Push(nCode);
Emi1(0x0F); // jxx Ofs
Emi1(jCode);
Emi2(0x00, 4);
end
word qFlag;
word Quit() is
if qFlag=1 then
EmiP(0xC7); // mov RAX, 03CH
Emi1(0xC0);
Emi2(0x3C, 4);
EmiP(0xC7); // mov RDI, 0
Emi1(0xC7);
Emi2(0x00, 4);
Emi1(0x0F); // syscall
Emi1(0x05);
end
if qFlag=0 then
Emi1(0xC3); // retn
end
end
word Obj (word T) is
if Cls[T]!=1 then
Stop();
end
Name[nName]:=nHeap;
Type[nName]:= T;
Scan();
if Find(1)1 then
Scan(); // [
Scan();
Expr();
if Size[Type[I]]>1 then
EmiP(0xC1); // shl RAX, 3
Emi1(0xE0);
Emi1(0x03);
end
LdIX(I);
EmiP(0x03); // add RAX, RBX
Emi1(0xC3);
Emi1(0x50); // push RAX
end
Scan(); // :=
Scan();
Expr();
Assign(I);
end
if Cls[I]=3 then
Expr();
end
rFlag:=1; // 14.05.2006
end
Scan();
end
word Func() is
Scan();
Ctrl();
while Comp(60)!=0 do // !end
Ctrl();
end
if rFlag!=0 then // 14.05.2006 // if rFlag=0 then
Quit();
end
end
word ReserveHdr() is
while nCode<0xB0 do
Emi1(0x00);
end
end
word FillHdr(word EP) is
Code[0x00]:=0x7F;
Code[0x01]:=byte('E');
Code[0x02]:=byte('L');
Code[0x03]:=byte('F');
Code[0x04]:=0x02; // 64bit
Code[0x05]:=0x01; // LSB
Code[0x06]:=0x01; // Version
Code[0x10]:=0x02; // ET_EXEC
Code[0x12]:=0x3E; // EM_X86_64
Code[0x14]:=0x01; // Version
Emi3(0x18, EP, 8); // Entry point
Code[0x20]:=0x40; // e_phofs
Code[0x28]:=0x00; // e_shofs
Code[0x30]:=0x00; // e_flags
Code[0x34]:=0x40; // e_ehsize
Code[0x36]:=0x38; // e_phentsize
Code[0x38]:=0x02; // e_phnum
Code[0x3A]:=0x40; // e_shentsize
Code[0x3C]:=0x00; // e_shnum
Code[0x3E]:=0x00; // e_shstrndx
Code[0x40]:=0x01; // PT_LOAD
Code[0x44]:=0x05; // p_flags
Code[0x48]:=0xB0; // p_offset
Code[0x50]:=0xB0; // p_vaddr
Code[0x51]:=0x80;
Code[0x52]:=0x04;
Code[0x53]:=0x08;
Code[0x58]:=Code[0x50]; // p_paddr
Code[0x59]:=Code[0x51];
Code[0x5A]:=Code[0x52];
Code[0x5B]:=Code[0x53];
Emi3(0x60,nCode-0xB0,8); // p_filesz
Emi3(0x68,nCode-0xB0,8); // p_memsiz
Code[0x70]:=0x00; // p_align
Code[0x71]:=0x10;
Code[0x78]:=0x01; // PT_LOAD
Code[0x7C]:=0x06; // p_flags
Emi3(0x80, nCode, 8); // p_offset
Code[0x88]:=0x00; // p_vaddr
Code[0x89]:=0xC0;
Code[0x8A]:=0x04;
Code[0x8B]:=0x08;
Code[0x90]:=Code[0x88]; // p_paddr
Code[0x91]:=Code[0x89];
Code[0x92]:=Code[0x8A];
Code[0x93]:=Code[0x8B];
//Emi3(0x98,nData-pData,8);// p_filesz
Emi3(0xA0,nData-pData,8);// p_memsz
Code[0xA8]:=0x00; // p_align
Code[0xA9]:=0x10;
end
word WriteBin() is
hFile:=create();
write();
close();
end
word Compile() is
OpenSrc();
qFlag:=0;
ReserveHdr();
Scan();
while Comp(31)!=0 do // !begin
Obj (Find(0));
char Ch:=Buff[0];
if Ch ='(' then
Cls [nName]:= 3;
Sub [nName]:= 0;
Ofs [nName]:=nCode;
nName :=nName+1;
Push(nName);
Scan(); // )
if Buff[0]!=')' then
Obj (Find(0));
while Var(1)=',' do
Scan();
Obj (Find(0));
end
end
Scan(); // is
Func();
Hide();
end
if Ch!='(' then
Var(0);
end
Scan();
end
word EP:=nCode+0x08048000;
qFlag:=1;
Func ();
FillHdr(EP);
CloseSrc();
WriteBin();
end
begin
Init();
Compile();
end