Приведенный здесь 64-х разрядный компилятор языка TinyContext является аналогом
32-х разрядного компилятора TinyContext и может быть
скомпилирован с его помощью. Для этого нужно в приведенном тексте заменить все функции
ввода-вывода 32-х разрядными аналогами и получить кросс-компилятор.
Затем с его помощью получить 64-х разрядный компилятор.
К сожалению, в отличие от версий для других платформ, объем исходного текста превышает 1000 строк.
Компилируемая программа должна помещаться в файл с именем c.prg, результат компиляции
записывается в файл с именем 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