flat assembler
Message board for the users of flat assembler.

flat assembler > Projects and Ideas > Universal Fasm

Author
Thread Post new topic Reply to topic
emil



Joined: 16 Dec 2003
Posts: 75
Location: egypt
hi all ,

my main goal is to make a compiler that will understand small basic of many programming languages syntax, such as C,pascal,basic,powerbasic, sphinx c--,asm,Amiga BlitzBasic2 , Oxygen basic ,and so on. ofcourse that will mix with Fasm as a backend.

at the same time i want it to be simple and easy , so that i have picked up the small C and tried to extend it.

i have made some progress in that , if any one interested and want to contribute me , i will go ahead and post the project here .

Notewell , it is a beta stage , so may has a bugs

here is a small Example
Code:
// // test program // format PE GUI //this is inline asm entry main // start point is main c function include 'MACRO/PROC32.inc' ; tell fasm to include PORC32.inc header file // declare a function that called from c code later extern stdcall MessageBoxA(); $ nop // empty section gives error // declare a global c variable int val = 100; /* Fasm Proc syntax , found in fasm forum */ proc itoa value,buf,base local table db '0123456789ABCDEF' ;Table used in conversion cmp [base],16 ;Nothing over base 16(Hex) is supported. You could add support for them by just modifying this line and the table above ja .base_error cmp [base],2 ;Nothing below base 2 is supported jb .base_error pushad ;Save the registers. No one likes a procedure that thrashes everything mov eax,[value] ;Load up the registers mov ebx,[base] mov edi,[buf] mov edx,0 ;Important note if you didn't know this, division by a dword is a 64-bit divide, edx will interfere if it's not cleared ;Division by a dword does edx:eax div r/m32 where edx:eax is treated as one 64-bit number push 0xFFFF ;This push is used later in the reversing part, it tells it that it's done. @@: or eax,eax ;Is the value to convert zero? jz .reverse ;If so, we're done here, lets reverse it. div ebx ;Else, divide it by the base. Result stored in eax, remainder in edx lea edx,[edx+table] ;Point edx to the byte in the table holding the value we need movzx edx,byte[edx] ;Put that byte in edx push edx ;Push it mov edx,0 ;and as I explained earlier, edx MUST be zero before the next divide, or it will interfere with the divide jmp @b ;Lather, rinse, and repeat ;The routine above gets the numbers backwards, so we must reverse them. .reverse: pop eax ;Pop a converted value off the stack cmp eax,0xFFFF ;Are we done reversing(was the popped value the 0xFFFF we pushed before we started)? je @f stosb ;If not, store the byte in the buffer jmp .reverse @@: mov eax,0 ;The string needs to be zero terminated, so this just places a 0x0 at the end stosb popad mov eax,0 ;Out: eax = 0, everything went fine ret .base_error: mov eax,-1 ;Out: eax = -1, Bad base ret endp /* c function Sytax */ print(x) int x; { char buf[255]; itoa(x,buf,10); MessageBoxA(0,buf,"the Value Is",0); } main() { int k,m,c; k = 10; m = 20; c = m + k + val; print(c); } #asm section '.idata' import data readable writeable dd 0,0,0,RVA kernel_name,RVA kernel_table dd 0,0,0,RVA user_name,RVA user_table dd 0,0,0,0,0 kernel_table: ExitProcess dd RVA _ExitProcess dd 0 user_table: MessageBoxA dd RVA _MessageBoxA dd 0 kernel_name db 'KERNEL32.DLL',0 user_name db 'USER32.DLL',0 _ExitProcess dw 0 db 'ExitProcess',0 _MessageBoxA dw 0 db 'MessageBoxA',0 section '.reloc' fixups data readable discardable ; needed for Win32s #endasm


i will post more examples , and post the source code fro contributing.

waiting for your opinion.
Post 21 Feb 2015, 19:27
View user's profile Send private message Reply with quote
HaHaAnonymous



Joined: 02 Dec 2012
Posts: 1171
Location: Unknown
Stupid post removed.


Last edited by HaHaAnonymous on 28 Feb 2015, 17:54; edited 1 time in total
Post 21 Feb 2015, 19:37
View user's profile Send private message Reply with quote
emil



Joined: 16 Dec 2003
Posts: 75
Location: egypt
HaHaAnonymous wrote:

If that will be achieved without inserting compiler directives (e.g.: c_code_start, c_code_end and bla bla bla) then that will be amazing! Very Happy


ofcourse my goal is without any directive , i made some progress , but still there are long work have to be done.

you can see from previous Example that Proc is a directive that accepts asm syntax untill endp directive found so here is the main Pares function

Code:
void parse() { while (eof == 0) { if (amatch("extern", 6)) { if(match("WINAPI")) doextern(); else if(match("stdcall")) dodeclare(EXTERNAL); else {match("cdecl"); dodeclare(EXTERNAL_C);}} else if(dodeclare(STATIC)); else if( match("#asm")) doasm(); else if( match("#include")) doinclude(); else if( match("#incpath")) doincludepath(); else if( match("#define")) dodefine(); else if( match("$")) doinlineasm(); else if( match("procedure")) {Pasfunc = -1; doprocedure();} else if( match("function")) {Pasfunc = 0; doprocedure();} else if( match("sub")) dosub(); else if( match("fastproc")) dofastproc(); else if( match("proc")) doproc(); else if( match("statement")) doBlitzStmt(); else if( match(".")) doBltz2subrotin(); else if( match("#")) doBltzResidnt(); else if(doglblabel()) ; else if( dofunction() == 0 ) { ccode = ASM_code; fputs(lptr, output); fputs("\15", output); Inline(); ccode = C_code; } blanks(); /* force eof if pending */ } }


as you can see compiler will act , i hope that , in language block.

here is a big test Example
=====================
File test6.c
Code:
// // test program // format PE console include 'win32ax.inc' entry start char tmp[255]; int cmnd; dim as integer stdout; dim dff.b,sdd.w,ase.l; dim Adff.b[20],Asdd.w(5),Aase.l[2*2]; int ary2[10][4]={1,0,8,7}; short sWord; CurTime: dd 0 totTime: db 2 shrTime: dw 1 extern stdcall MessageBoxA(); extern stdcall GetCommandLine(); extern stdcall GlobalAlloc(); extern stdcall GlobalFree(); extern WINAPI "msvcrt.dll" { printf(); cdecl system(); exit(); } #WINDOWS_7 = 3 //#define WINDOWS_7 3 mydata: Dc.w 10,15,13; #include "test6_1.c" #include "test6_3.c" #include "test6_4.c" #include "test6_5.c" #include "test6_6.c" #asm .data _caption db 'Win32 assembly program',0 _message db 'Hello World!',0 display_handle dd 0 .code start: mov [display_handle],STD_OUTPUT_HANDLE invoke GetStdHandle,[display_handle] mov [stdout],eax GetCommandLine (); // using high level function call mov [cmnd],eax call main printf("\n\nbay ...."); system("pause>NULL"); push 0 call [ExitProcess] ;==========[ Import Sec ]======= section '.idata' import data readable writeable library msvcrt, 'msvcrt.dll', kernel32, 'kernel32.dll', user32, 'user32.dll', advapi32, 'advapi32.dll', shell32, 'shell32.dll' import_kernel32 import_user32 import_gdi32 import_advapi32 import_comctl32 import_comdlg32 import_shell32 import_wsock32 import msvcrt, printf, 'printf', system, 'system' all_api #endasm


file test6_1.c
==========
Code:
#include "test6_2.c" procedure MsgBox; begin MessageBoxA(0,"i am pascal","",0); $ invoke MessageBoxA,HWND_DESKTOP,"Hi! I'm the example program!",invoke GetCommandLine,MB_OK end; procedure MyAdd(x,y)int x,y; begin return x+y; end; procedure MyAdd2(x,y)int x,y; var int k,p; begin k = 10; p := 20; return x+y+k; end; procedure findMin(x,y,z,m)int x,y,z;int* m; /* (x, y, z: integer; var m: integer); */ /* Finds the minimum of the 3 values */ begin if x < y then m := x; else m := y; if z <m then m := z; end; /*{ end of procedure findMin }*/ /* function returning the max between two numbers */ function max(num1,num2) int num1,num2; /*(num1, num2: integer): integer;*/ var /* local variable declaration */ /* result: integer; */ int result; begin if (num1 > num2) then result := num1; else result := num2; max := result; end;


file test6_2.c
==========
Code:
print(x)int x; { int p; if(x) p=10; $ push 0 $ push _caption $ push _message $ push 0 $ call [MessageBoxA] } print2(char x,int y) { int p; if(x) p=10; $ push 0 $ push _caption $ push _message $ push 0 $ call [MessageBoxA] tmp[0] = 0; } strlen(char *s) { char *ptr; ptr=s; while(*ptr) { ++ptr; } return (ptr-s); }


file test6_3.c
==========
Code:
#asm .data bytes_count dd 0 .code display_string: mov edi,esi or ecx,-1 xor al,al repne scasb neg ecx sub ecx,2 invoke WriteFile,dword[stdout],esi,ecx,bytes_count,0 retn #endasm .bltzRotn Adff[2] = Adff[1] + 2; return .SubRotn: Adff[1] = 5*30+1; gosub bltzRotn; return main() { local pp; int k,m,c; int* ptr; DEFTYPE.w lm,ld dim cc.b,bb.l,kk.w cc = 'A'; bb = -10; kk = 0xFFFF; dff = cc; sdd = kk; ase = bb; Aase[2]= bb * 2; gosub SubRotn; mov EAX , WINDOWS_7; print(5); k = 10; m = k > 5 ? 30 : 60; ptr = &m; // lm = 100; // ld = 200; MsgBox(); MyAdd(20,40); MyAdd2(60,80); max(30,40); emit(); empty(); fast(); fast2(c); #asm stdcall itoa,4660,tmp,10 invoke MessageBoxA,HWND_DESKTOP,tmp,"the number is",MB_OK mov ESI,[cmnd] call display_string #endasm push 6*m +20 , EDX + 5; pop EDX , m; push EAX; $pop eax mov EDX , 10*k+c; mov m , 10*k+ 4 : ECX , 10 : ESI , strlen(tmp); EDX = 10 * max(200,300); DX = 10 * max(200,300); DL = 10 * max(10,30) + CH; lea EDX , [strlen] ECX=EDX(tmp); sWord = 50; DX = sWord * 20; mov ESI,cmnd; display_string(); EDX = GetCommandLine(); MessageBoxA(HWND_DESKTOP,"Hi! I'm the example program!",EDX,MB_OK); MessageBoxA(HWND_DESKTOP,_message,_caption,MB_OK); // MessageBoxA(HWND_DESKTOP,"Hi! I'm the example program!",GetCommandLine(),MB_OK); itoa(0xffef,tmp,16); // MessageBoxA(HWND_DESKTOP,tmp,cmnd,MB_OK); push MB_OK,cmnd,tmp,HWND_DESKTOP; call MessageBoxA ptr = sizeof int; ptr = new int[100]; delete ptr; MessageBoxA(HWND_DESKTOP,"...Good bay...","",MB_OK); } #asm __NEW: push eax push GMEM_FIXED call [GlobalAlloc] ret __DELETE: push eax call [GlobalFree] ret #endasm


file test6_4.c
==========
Code:
sub empty; /* */ tmp[0] = 0; endsub sub emit() int h; h = 500; $ invoke MessageBoxA,HWND_DESKTOP,"I'm in subroutin","",MB_OK begin h = h + 1; end; endsub fastproc fast; $ mov eax,1 endfastproc fastproc fast2(x) int x; $ mov eax,1 $ add eax, [esp+4] ; eax = x + 1 endfastproc fastproc fast3(ECX,EDX) $ mov eax,edx EAX = ECX * 2 + EDX; endfastproc


file test6_5.c
==========
Code:
/* value,buf,base ;Return will be in eax, 0:fine, -1:base too small/large */ proc itoa value,buf,base local table db '0123456789ABCDEF' ;Table used in conversion cmp [base],16 ;Nothing over base 16(Hex) is supported. You could add support for them by just modifying this line and the table above ja .base_error cmp [base],2 ;Nothing below base 2 is supported jb .base_error pushad ;Save the registers. No one likes a procedure that thrashes everything mov eax,[value] ;Load up the registers mov ebx,[base] mov edi,[buf] mov edx,0 ;Important note if you didn't know this, division by a dword is a 64-bit divide, edx will interfere if it's not cleared ;Division by a dword does edx:eax div r/m32 where edx:eax is treated as one 64-bit number push 0xFFFF ;This push is used later in the reversing part, it tells it that it's done. @@: or eax,eax ;Is the value to convert zero? jz .reverse ;If so, we're done here, lets reverse it. div ebx ;Else, divide it by the base. Result stored in eax, remainder in edx lea edx,[edx+table] ;Point edx to the byte in the table holding the value we need movzx edx,byte[edx] ;Put that byte in edx push edx ;Push it mov edx,0 ;and as I explained earlier, edx MUST be zero before the next divide, or it will interfere with the divide jmp @b ;Lather, rinse, and repeat ;The routine above gets the numbers backwards, so we must reverse them. .reverse: pop eax ;Pop a converted value off the stack cmp eax,0xFFFF ;Are we done reversing(was the popped value the 0xFFFF we pushed before we started)? je @f stosb ;If not, store the byte in the buffer jmp .reverse @@: mov eax,0 ;The string needs to be zero terminated, so this just places a 0x0 at the end stosb popad mov eax,0 ;Out: eax = 0, everything went fine ret .base_error: mov eax,-1 ;Out: eax = -1, Bad base ret endp


file test6_6.c
==========
Code:
statement bltzAdd{ kilo.l , metr.w , mch.b } int cc; cc = 10; tmp[cc+10] = 2; if ( cmnd == 0 ) cmnd = 0; ary2[6][2] = 5; endstatement
Post 21 Feb 2015, 20:08
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
emil,

Please, add Brainfuck to the list… Wink

Compiler using fasm as a back-end? That would be great.
Post 22 Feb 2015, 09:53
View user's profile Send private message Reply with quote
emil



Joined: 16 Dec 2003
Posts: 75
Location: egypt
baldr;

hope you will like it , as i mintioned above , i have picked up Small C that found in fasm forum that was already uese Fasm as a backend.

i have only extend it , it is not optimized yet , in this stage focus in muliti language compatibility.

ok here is another Example , showing you how to declare a global variable in
many language syntax then use them as usual variable.
Code:
// // Global Decleraion test program // format PE console include 'win32ax.inc' entry main // c syntax decleration char chr; int cmnd; short sWord; unsigned len; char name[255]; char* Cptr; int* Aptr; int scrn[200][100]; // basic syntax dim as integer stdout; dim as char basic_char; dim as word basic_word; //Amiga BlitzBasic2 syntax dim dff.b,sdd.w,ase.l; dim Adff.b[20],Asdd.w(5),Aase.l[2*2]; DEFTYPE.w lm,ld; // fasm syntax CurTime: dd 0 totTime: db 2 shrTime: dw 1 //Amiga Asm syntax mydata: Dc.w 10,15,13; // inline fasm syntax #asm .data caption db 'AAAAAA',0 message db 'HHHHHH',0 disply dd 0 #endasm extern printf(); extern exit(); extern system(); init() { int i,j; chr = 'A'; cmnd = 100; sWord = 200; len = 2000; for(i=0;i<254;i++) name[i]='A'; Cptr = &name[100]; for(i=0;i<200;i++) for(j=0;j<100;j++) scrn[i+j*200]=i+j; Aptr = scrn; stdout = 100; basic_char = name[50]; basic_word = 0xFFEE; dff = 0xAA; sdd = 0xAABB; ase = 0xAABBCCDD; Adff[10] = 0x11; Asdd[2] = 0x1122; Aase[3] = 0x11223344; lm = ld = Asdd[2]; CurTime = 0xFFAAAAFF; //amazing using it as usual variable totTime = 0x55; //amazing using it as usual variable shrTime = 0x2288; //amazing using it as usual variable // mydata = 10; // in todo list caption = 'C'; //amazing using it as usual variable message = 'A'; disply = 300; //amazing using it as usual variable } main() { init(); printf( "Test program\n" ); printf( "%d\n", disply ); printf( "%c\n", message ); printf( "%c\n", caption ); printf( "%x\n", shrTime ); //did not work correctly ,i will see printf( "%x\n", totTime ); printf( "%x\n", CurTime ); system( "pause>NULL" ); exit(0); } section 'idata' import data readable library msvcrt, 'msvcrt.dll' import msvcrt, system,'system',printf,'printf',exit,'exit'
Post 22 Feb 2015, 17:39
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >

Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 2004-2018, Tomasz Grysztar.

Powered by rwasa.