Yet another simple compiler for Linux/AMD64

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 <N do Emi1(W%256); W :=W/256; P :=P+1; end end word Emi3(word P, word W, word N) is word Q :=P+N; while P <Q do Code[P]:=W%256; W :=W/256; P :=P+1; end end byte EmiP(byte B) is Emi1(0x48); // 64 bit prefix Emi1(B); end word LdIX(word I) is if Ofs[I]<=0xFFFFFFFF then Emi1(0xBB); // mov RBX, Ofs Emi2(Ofs[I], 4); end if Ofs[I]> 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)<nName then Stop(); end word pBuff:=0; char Ch :=char(1); while Ch !=char(0) do Ch := Buff[pBuff]; Heap[nHeap]:= Ch; nHeap :=nHeap+1; pBuff :=pBuff+1; end Scan(); return nName; end char Var (word Subclass) is Cls [nName]:= 2; Sub [nName]:= Subclass; Size[nName]:= 1; Ofs [nName]:=nData; if Buff[0]='[' then if Subclass!=0 then Stop(); end Scan(); Size[nName]:=val(); Scan(); // ] Scan(); // ; end nData :=nData+(Size[Type[nName]]*Size[nName]); while nData%8!=0 do nData :=nData+1; end nName :=nName+1; return Buff[0]; end word Hide() is word I:=Pop(); while I< nName do Heap[Name[I]]:=char(0); I :=I+1; end end word rFlag; word Ctrl() is word cFlag:=0; //if cFlag =0 then if Comp(37)=0 then // if Cond(); Push(nName); Scan(); Ctrl(); while Comp(60)!=0 do // !end Ctrl(); end Hide(); word pSkip:=Pop(); Emi3(pSkip+2, (nCode-pSkip)-6, 4); rFlag:=1; // 14.05.2006 cFlag:=1; end //end if cFlag =0 then if Comp(40)=0 then // while Push(nCode); Cond(); Push(nName); Scan(); Ctrl(); while Comp(60)!=0 do // !end Ctrl(); end Hide(); word pExit:=Pop (); word pLoop:=Pop (); Emi1(0xE9); // jmp Ofs Emi2((0xFFFFFFFF-((nCode+4)-pLoop))+1, 4); Emi3(pExit+2, (nCode-pExit)-6, 4); rFlag:=1; // 14.05.2006 cFlag:=1; end end if cFlag =0 then if Comp(46)=0 then // inline Buff[0]:=','; while Buff[0]=',' do Scan(); Emi1(val()); // db Val Scan(); end rFlag:=1; // 14.05.2006 cFlag:=1; end end if cFlag =0 then if Comp(53)=0 then // return Scan(); Expr(); Quit(); rFlag:=0; cFlag:=1; end end if cFlag =0 then word I:=Find(0); if Cls[I]=1 then word N:=Obj(I); if Var(2)=':' then Scan(); Expr(); Assign(N); end end if Cls[I]=2 then if Size[I]>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

32-bit I/O functions for cross compiler

word open() is inline 0xB8, 0x05, 0x00, 0x00, 0x00; // mov EAX, 5 inline 0xBB, 0x54, 0x40, 0x05, 0x08; // mov EBX, @@DATA+Ofs(Heap[64]) inline 0xB9, 0x00, 0x00, 0x00, 0x00; // mov ECX, 0 inline 0xBA, 0x00, 0x00, 0x00, 0x00; // mov EDX, 0 inline 0xCD, 0x80; // int 80H end word create() is inline 0xB8, 0x05, 0x00, 0x00, 0x00; // mov EAX, 5 inline 0xBB, 0x5A, 0x40, 0x05, 0x08; // mov EBX, @@DATA+Ofs(Heap[70]) inline 0xB9, 0x41, 0x02, 0x00, 0x00; // mov ECX, 241H inline 0xBA, 0xED, 0x01, 0x00, 0x00; // mov EDX, 1EDH inline 0xCD, 0x80; // int 80H end word read() is inline 0xB8, 0x03, 0x00, 0x00, 0x00; // mov EAX, 3 inline 0x8B, 0x1D, 0x10, 0x40, 0x05, 0x08; // mov EBX, dword [@@DATA+Ofs(hFile)] inline 0xB9, 0x00, 0xC0, 0x04, 0x08; // mov ECX, @@DATA+Ofs(Text) inline 0xBA, 0x00, 0x40, 0x00, 0x00; // mov EDX, 16384 inline 0xCD, 0x80; // int 80H end word write() is inline 0xB8, 0x04, 0x00, 0x00, 0x00; // mov EAX, 4 inline 0x8B, 0x1D, 0x10, 0x40, 0x05, 0x08; // mov EBX, dword [@@DATA+Ofs(hFile)] inline 0xB9, 0x0C, 0x00, 0x05, 0x08; // mov ECX, @@DATA+Ofs(Code) inline 0x8B, 0x15, 0x0C, 0x40, 0x05, 0x08; // mov EDX, dword [@@DATA+Ofs(nCode)] inline 0xCD, 0x80; // int 80H end word close() is inline 0xB8, 0x06, 0x00, 0x00, 0x00; // mov EAX, 6 inline 0x8B, 0x1D, 0x10, 0x40, 0x05, 0x08; // mov EBX, dword [@@DATA+Ofs(hFile)] inline 0xCD, 0x80; // int 80H end word puts() is inline 0xB8, 0x04, 0x00, 0x00, 0x00; // mov EAX, 4 inline 0xBB, 0x01, 0x00, 0x00, 0x00; // mov EBX, 1 inline 0xB9, 0x28, 0x56, 0x05, 0x08; // mov ECX, @@DATA+Ofs(Buff) inline 0x8B, 0x15, 0xA8, 0x56, 0x05, 0x08; // mov EDX, dword [@@DATA+Ofs(nBuff)] inline 0xCD, 0x80; // int 80H end word halt() is inline 0xB8, 0x01, 0x00, 0x00, 0x00; // mov EAX, 1 inline 0xBB, 0x01, 0x00, 0x00, 0x00; // mov EBX, 1 inline 0xCD, 0x80; // int 80H end


Сайт создан в системе uCoz