BASIC Developer & Support Resources > Compilers

Alternative O2 Builder

(1/7) > >>


I have been sifting through your source code and from what I see, FreeBASIC is being used as an scripting engine to build a ASM source code program. Instead of using an external assembler, O2 embeds it's generated source as inline ASM statements which FreeBASIC assembles and does any linking that needs to be done.

For grins, lets say I was able to convert the FreeBASIC version of O2 to ScriptBasic and used the gcc's inline ASM feature to create the O2 compiler. Is this theoretically possible?

Wouldn't that offload all that work you have to do to be C friendly? (read C headers, let C be your generic interface helper shell, expand to cross platform, ...)


--- Quote from: Charles - FreeBASIC Forum ---Hi everyone!

Thank you very much for all your interesting comments on Oxygen Basic. I was about to announce the project on this forum, but John got in there first :)

I am more than satisfied with FreeBasic as a development language. While I have not made use of its more advanced features, it has proved to be very reliable, and interfaces nicely with assembly code. Thank you Joshy for posting the compatibility fix with FB 0.21

O2 was conceived nearly three years ago as a machine script, in essence machine code with a linker. It was an experiment to see how minimal a compilable language could be. Then came the Assembler shortly followed by a macro language. Eros Olmi (of thinBasic) suggested more people would be able to understand it if I added Basic-like syntax. So I thought okay, I'll have this ready in a few weeks. Little did I know how much work was involved in producing a high level compilable language. A compiler has to spend much of its time doing invisible things like automatic type conversion and operator precedence and one is not fully aware of these complexities until you try to encode them.

Even before adding Basic, I had OOP capability in place. I think retrofitting it to a straight procedural language would have been much more difficult which I think is why many Basics have got stuck in their development.

One very importand and most recent feature in the development of o2 is the ability to read C headers as well as Qbasic headers. This requires O2 to understand quite a large chunk of C itself. So far, this fusion of C and basic has not been too problematic. A Few directives are needed. For instance partial case sensitivity: #case capital which distinguishes fully capitalised keywords.

I use the term JIT because O2 compiles directly to an executable memory image which may be used immediately without first storing it to an EXE file. For programs up to about 40-50k of source code, the compilation time is barely noticeable. This is good for ad-hoc programming where you are not building a static application. The source code is the only item that needs to be stored.

Currently O2 compiled executables depend on Oxygen.dll for the run-time library, but I am working on the 'independent' mode where the run-time library is included. This is of course essential when generating 64bit code with a 32 bit compiler.

I am still devoted to GOTOs. But I have only used them very sparingly 372 times :D. Many of these are error trapping points, and many GOTOs are directed towards a small number of nodes in the program.

It will take about three more months to approach Beta quality releases. Much of the testing at this stage involves exposing Oxygen to as many different situations as possible and testing with various APIs.

--- End quote ---



Oxygen makes intensive use of FreeBasic Inline Assembler (which is slightly preprocessed GNU GAS using Intel notation). The Oxygen Assembly language is largely compatible with this. We also have a high degree of compatibility between FreeBasic and OxygenBasic language. Then there is the evolving C compatibility. And operating system dependencies are absolutely minimal at this stage so I hope this is sufficient to keep Oxygen's porting options open.

However porting to SB, being a scripting language would pose a few problems like being unable to tightly couple Assembly code with the host script. But theoretically any Turing machine will do.

Looking back over the last 35 years. What has been the most stable language? X86 Assembler!  ;D Who would have thought it! But so many other processors, despite their more elegant architecture, are rapidly heading for extinction, and the main rival is the ARM - whose cores are embedded in the processors of many mobile devices. ARM Assembler is a joy to code. I would love to develop an ARM version of Oxygen should the opportunity arise.



--- Quote ---However porting to SB, being a scripting language would pose a few problems like being unable to tightly couple Assembly code with the host script.
--- End quote ---

<Start Theory>ScriptBasic would only act as an interactive C/ASM source code generating tool. It outputs C / C inline ASM text to be compiled by a C compiler. Once you have a OxygenBasic compiler compiled, SB & gcc would no longer be required.<End Theory>

Maybe I don't fully understand the dependency on FreeBASIC when generic inline ASM is the outputted result. With no real development going on with FreeBASIC in years, it seems a bit risky to bet the farm on it.


Yes I see. I think I would either go for C or self-compile. But the worst that could happen to FB is going into stasis and that largely depends on its major users. The most useful thing about basic is good string manipulation and easy access to assembler. Compilers don't really require more than that.

I spend much of my time refactoring the source code (It can be Draconian sometimes.)  and FB is a comfortable and familiar environment to do this. And FB compiles O2 in less than 2 seconds. It is almost interactive. The only thing I really miss is GOSUB. I often need subroutines that have access to all the parental variables. This would reduce my global list considerably.


Your right. C or BCX makes more sense.

--- Quote from: BCX Docs ---$ASM directive

Purpose: The $ASM directive allows inline assembly instructions to be used with BCX. An $ASM directive must be placed before and after the assembly statements.


  /** Assembly statements go here */

--- End quote ---

--- Code: Text --- DIM str1$ DIM str2$    str1$ = "123456789"    str2$ = AsmLeft$(str1$, 3) PRINT str2$    str2$ = AsmMid$(str1$, 4, 3) PRINT str2$    str2$ = AsmMid$(str1$, 4) PRINT str2$    str2$ = AsmRight$(str1$, 3) PRINT str2$       FUNCTION SubStr%(SrcStr AS LPSTR, SrcStrLen%, StartPosn%, DestStr AS LPSTR, DestStrLen%)   $ASM   nop   nop   nop      ;save used registers except for eax:edx   push ebx   push ecx   push edi   push esi      ;load the 32-bit registers from the stack      mov esi, dword PTR [ebp+8]  ;SrcStr   mov edx, dword PTR [ebp+12] ;SrcLen   mov eax, dword PTR [ebp+16] ;StartPosn   mov edi, dword PTR [ebp+20] ;DestStr   mov ecx, dword PTR [ebp+24] ;DestLen      ;check for zero-length Destination string   jecxz NoGood      ;compensate StartPosn for 0 based count   dec eax      ;check for negative offset of StartPosn   cmp eax, 0   jl NoGood      ;point esi to start of SrcStr   add esi, eax      ;and subtract StartPosn from SrcLen   sub edx, eax      ;check if offset is past end of SrcStr   cmp edx, 0   jle NoGood      ;move substring of esi into edi   rep movsb      ;return this to indicate function worked   mov eax, edi   jmp ReturnAX      NoGood:   mov eax, -1      ReturnAX:   pop esi   pop edi   pop ecx   pop ebx   pop ebp   ret    $ASM   FUNCTION = 0 END FUNCTION    'Left$ equivalent FUNCTION AsmLeft$(fnstr1$, fnint1%)   DIM RAW startp% = 1   DIM RAW retstr$ * fnint1% + 256   SubStr(fnstr1$, LEN(fnstr1$), startp%, retstr$, fnint1%)   retstr[fnint1] = 0   FUNCTION = retstr$ END FUNCTION    'MID$ equivalent FUNCTION AsmMid$ OPTIONAL(fnstr1$, fnint1%, fnint2%=0)   DIM RAW startp% = fnint1%   DIM RAW lenfnstr1% = LEN(fnstr1$)   DIM RAW retstr$ * fnint2% + 256   IF fnint2% = 0 THEN     fnint2% = lenfnstr1% - startp% + 1   END IF   SubStr(fnstr1$, lenfnstr1%, startp%, retstr$, fnint2%)   retstr[fnint2] = 0   FUNCTION = retstr$ END FUNCTION    'RIGHT$ equivalent FUNCTION AsmRight$(fnstr1$, fnint1%)   DIM RAW lenfnstr1% = LEN(fnstr1$)   DIM RAW startp% = lenfnstr1% - fnint1% + 1   DIM RAW retstr$ * fnint1% + 256   SubStr(fnstr1$, lenfnstr1%, startp%, retstr$, fnint1%)   retstr[fnint1] = 0   FUNCTION = retstr$ END FUNCTION 

--- Quote ---GOSUB ... RETURN statement

Purpose: GOSUB redirects program flow to a label. The flow continues from the label until a RETURN statement is encountered and the flow is returned to the line following the GOSUB Label statement.


 GOSUB Label


--- End quote ---

--- Code: ---DIM j
 PRINT "Calling Subroutine 9 times ..." : PRINT
 FOR j = 1 TO 9
   GOSUB qwerty
 PRINT : PRINT "All Done!"
 END                       ' Don't accidently fall into the subroutine
 QwErTy:                   ' BCX Subroutine Labels are NOT case sensitive
 PRINT " This is instance >>", j, " <<  of the subroutine call."
 RETURN                    ' Return from subroutine back to main program

--- End code ---


[0] Message Index

[#] Next page

Go to full version