FreeBasic converts the BASIC statements into Assembly code in a file of the same
name, with a .ASM extension, then assembles that and links it with any other
dependent files to create the final name file with .EXE extension. This is called the executable, meaning the program to be actually executed.
If called from the command line in this manner: fbc -r <filename.BAS>, it will retain the significant part of the ASM code produced in the file with that extension. Like QBASIC/QuickBASIC/GWBASIC before it, FreeBASIC does not require a main-type FUNCTION in the source code, but on examining the ASM file, you will see that it in fact incorporates _Main in the produced file. PowerBasic does require a MAIN, PBMAIN, or WINMAIN function where the main body of code resides.
The simple program here was compiled in FreeBasic to see what it produces in the way of ASM instructions:
asm mov ah,ah
color 15,1
cls
a=12345
print "a ="; a
asm mov al,al
do
loop
As explained before, the assembler statements mov ah,ah and mov al,al make a good pair for blocking a section of code in BASIC so that it can
be easily found in the final assembly code.
I am currently using the PBIDE free IDE, and though it does not give me the
ability to set compiler options, I first saved and compiled the program above to make sure it workd, then I entered the command line mode where I typed fbc -r test,bas. I then loaded the resulting test.asm file so that I could look at it with any text editor. PBIDE will bring it up if you want, or you could use notepad or wordpad if you prefer,
This is what the ASM file looked like after I went through and indented each line, then used IDA PRO on the resulting exe file and parallelled the same portions so that you could compare the two:
FreeBASIC ASM File: | IDA PRO ASM Extract: .intel_syntax noprefix |
#test.bas' compilation started at 18:14:10 (FreeBASIC v0.15b)
|
.section .text |
.balign 16 |
|
.globl _main | sub_4012D0 proc near ; CODE XREF: sub_4011E0+48p
| arg_0 = dword ptr 8
} arg_4 = dword ptr 0Ch
_main: |
push ebp | push ebp
mov ebp, esp | mov ebp, esp
and esp, 0xFFFFFFF0 | and esp, 0FFFFFFF0h
push ebx | push ebx
push esi | push esi
push edi | push edi
call ___main | call sub_4041D0
push dword ptr [ebp+12] | push [ebp+arg_4]
push dword ptr [ebp+8] | push [ebp+arg_0
call _fb_Init@8 | call sub_401350
call _fb_CallCTORS | call sub_4013B0
.Lt_0001: |
mov ah,ah | mov ah, ah
push 1 | push 1
push 15 | push 0Fh
call _fb_Color@8 | call sub_401410
push -65536 | push 0FFFF0000h
call _fb_Cls@4 | call sub_401450
mov dword ptr [_Ai], 12345 | mov ds:dword_407000, 3039h
push 0 | push 0
push 3 | push 3
push offset Lt_0003 | push offset unk_405010
call _fb_StrAllocTempDescZEx@8 call sub_4014A0
push eax | push eax
push 0 | push 0
call _fb_PrintString@12 | call sub_401590
push 1 | push 1
push dword ptr [_Ai] | push ds:dword_407000
push 0 | push 0
call _fb_PrintInt@12 | call sub_4015F0
mov al,al | mov al, al
.Lt_0004: | loc_401334: ; CODE XREF: sub_4012D0+64j
.Lt_0006: |
jmp .Lt_0004 | jmp short loc_401334
.Lt_0005: |
.Lt_0002: | sub_4012D0 endp
push 0 | push 0
call _fb_End@4 | call sub_401810
pop edi | pop edi
pop esi | pop esi
pop ebx | pop ebx
mov esp, ebp | mov esp, ebp
pop ebp | pop ebp
ret | retn
|
#test.bas' compilation took 3.33561947538641e-004 secs
#global initialized constants |
|
.section .data |
.balign 16 | align 10h
.balign 4 |
Lt_0003: |
.ascii "a =\0" | unk_405010 db 61h ; a ; DATA XREF: sub_4012D0+41o
| db 20h ;
| db 3Dh ; =
| db 0 ;
|
|
#global non-initialized vars |
|
.section .bss | ;Segment type: Uninitialized
| _bss segment para public 'BSS' use32
| assume cs:_bss
| ;org 407000h
| assume es:nothing, ss:nothing, ds:_data, fs:nothing, gs:nothing
.balign 16 |
.balign 4 |
.lcomm _Ai,4 | dword_407000 dd ? ; DATA XREF: sub_4012D0+33w
| ; sub_4012D0+55r
By comparing the two results side by side, you can see that in some ways, the
output from FreeBASIC is more user friendly - the names it uses in the CALL statements give you some idea of what the called process will likely do. But it
is at the same time incomplete - all those called processas are absent. The
IDA PRO's resulting file is quite large, because it contains all the missing procedures, and a lot of apparent data segments in byte format.