I was pleased with having some control over the IDE that PBEdit supplies, so I wanted to see what else I could do. Looking under Options again, you see a button called Build Options. When you left click on it, you will see a dialog open up with several options listed, which probably includes Windows GUI, Windows GUI (Debug), Windows Console, Windows Console (Debug), Windows DLL, and Library. If you click on each link, you will see the two lower fields change, with the second field showing a compiler call with different switches. You will also see an Insert and Delete button on the right.
As an experiment, I selected Insert, and a blank place appeared in the list. I then typed in Compile and Keep ASM File for my menu item, and fpc -r for my command. I then picked one of my test BAS files and loaded it, then did a compile with my new build option selected (the current build option appears in a box on the right side of the tool bar). This is the test file I compiled:
dim aa as string
dim a as long, b, c, d, e, f, g, h
color 15,1
cls
aa="This is a test."
a=12345
print aa, "a ="; a
do while inkey$=""
loop
The next thing I did was attempt to open another file, but this time I indicated that I wanted to see all files, then I picked the one labelled test.asm. This is the file that was created using the fbc -r "test.bas" command, used by the IDE in response to my new build option. The FBEdit then opened another file tab and showed me the contents of the resulting ASM stage. Thus, I now had this file on my screen:
.intel_syntax noprefix
#test.bas' compilation started at 22:40:36 (FreeBASIC v0.15b)
.section .text
.balign 16
.globl _main
_main:
push ebp
mov ebp, esp
and esp, 0xFFFFFFF0
call ___main
push dword ptr [ebp+12]
push dword ptr [ebp+8]
call _fb_Init@8
call _fb_CallCTORS
.Lt_0001:
push 1
push 15
call _fb_Color@8
push -65536
call _fb_Cls@4
push 0
push 16
push offset Lt_0003
push -1
push offset _AA
call _fb_StrAssign@20
mov dword ptr [_A], 12345
push 2
push offset _AA
push 0
call _fb_PrintString@12
push 0
push 3
push offset Lt_0004
call _fb_StrAllocTempDescZEx@8
push eax
push 0
call _fb_PrintString@12
push 1
push dword ptr [_A]
push 0
call _fb_PrintInt@12
.Lt_0005:
push 1
push offset Lt_0000
push -1
call _fb_Inkey@0
push eax
call _fb_StrCompare@16
test eax, eax
jne .Lt_0006
jmp .Lt_0005
.Lt_0006:
.Lt_0002:
push 0
call _fb_End@4
mov esp, ebp
pop ebp
ret
#test.bas' compilation took 2.86069876599626e-004 secs
#global initialized constants
.section .data
.balign 16
.balign 4
Lt_0000: .ascii "\0"
.balign 4
Lt_0003: .ascii "This is a test.\0"
.balign 4
Lt_0004: .ascii "a =\0"
#global non-initialized vars
.section .bss
.balign 16
.balign 4
.lcomm _AA,12
.balign 4
.lcomm _A,4
.balign 4
.lcomm _Bi,4
.balign 4
.lcomm _Ci,4
.balign 4
.lcomm _Di,4
.balign 4
.lcomm _Ei,4
.balign 4
.lcomm _Fi,4
.balign 4
.lcomm _Gi,4
.balign 4
.lcomm _Hi,4
This is the partial result in assembly form created during the compile process.
The only part really missing are the automatic constructs needed for actually
creating the resulting EXE file, and the appended procedures you see that are being called, and other procedure that might be called in turn, as these would be needed to complete the program. These results are somewhat unstructured,
in that most assembly code is indented and aligned vertically, but still very useful. Now we are going to look at the same assembly results again, and this time try to deduce what might be going on. Not being real familiar with FreeBasic, I can only draw some preliminary conclusions at this point. But you have to start somewhere:
.intel_syntax noprefix
#test.bas' compilation started at 22:40:36 (FreeBASIC v0.15b)
.section .text 'we saw with IDE PRO that this was the CODE section
.balign 16
.globl _main 'Since no function was started, this must be the main code
_main:
push ebp 'we've discussed saving EBP contents on stack before
mov ebp, esp 'then using EBP to hold current ESP contents
and esp, 0xFFFFFFF0 'here the contents of ESP are forced to align16
call ___main 'this is FreeBasic's Main procedure
push dword ptr [ebp+12] 'an existing value on stack is pushed on stack again
push dword ptr [ebp+8] 'a second existing stack value is pushed on stack again
call _fb_Init@8 'another FreeBasic procedure is called
call _fb_CallCTORS 'and another FreeBasic procedure is called
.Lt_0001:
push 1 'first parameter pushed is background color (Blue)
push 15 '2nd paramter pushed is forground color (Br White)
call _fb_Color@8 'this is the COLOR command routine in FreeBasic
push -65536 'This is a parameter for the CLS command
call _fb_Cls@4 'this it the CLS routine for FreeBASIC
push 0 'we are probably singnalling at same location
push 16 'we need 15 bytes, plus 1 for a null terminator
push offset Lt_0003 'and the stromg constant starts here
push -1 'and we want to assign this to a dynamic string
push offset _AA 'that we allocated to start here
call _fb_StrAssign@20 'this sets our dynamic string to the constant
mov dword ptr [_A], 12345 'now we do the "a = 12345" FB instruction
push 2 'we signal that we want a tab done first
push offset _AA 'and what we want to print next
push 0 'probably the device to print to (console)
call _fb_PrintString@12 'this will perform our FB "print aa;" instruction
push 0 'print at current location again
push 3 'the string consists of three characters
push offset Lt_0004 'this is where our "a =\0" constant is stored
call _fb_StrAllocTempDescZEx@8 'make this into a temporary dynamic string
push eax 'eax contains where the temporary string is
push 0 'print to the console screen again
call _fb_PrintString@12 'this is what does the string printing
push 1 'indicate that we are pushing a numberic value
push dword ptr [_A] 'put the value on the stack (12345)
push 0 'print to console screen flag
call _fb_PrintInt@12 'this routine is what prints integers
.Lt_0005:
push 1 'indicate just one byte
push offset Lt_0000 'push a null byte on stack
push -1 'could indicate device, or nowait state?
call _fb_Inkey@0 'This is where FB does the INKEY$ function
push eax 'put the return code from INKEY$ on stack
call _fb_StrCompare@16 'see if it is a match for the null byte on stack
test eax, eax 'see if the results in EAX are a match
jne .Lt_0006 'if no match, we are done
jmp .Lt_0005 'it was a null char (or no keypress) so loop
.Lt_0006: 'a key was pressed, so here we are
.Lt_0002: 'seems there is always a label after a LOOP
push 0 'We set a zero as our return code
call _fb_End@4 'FreeBasic's END routine, restores saved regs
mov esp, ebp 'This is that neat trick that allows the ESP to be wiped of temps
pop ebp 'and final step to restore EBP from stack
ret 'and we are done
#test.bas' compilation took 2.86069876599626e-004 secs
#global initialized constants
.section .data
.balign 16
.balign 4
Lt_0000: .ascii "\0"
.balign 4
Lt_0003: .ascii "This is a test.\0"
.balign 4
Lt_0004: .ascii "a =\0"
#global non-initialized vars
.section .bss
.balign 16
.balign 4
.lcomm _AA,12 'this is dynamic string variable AA
.balign 4
.lcomm _A,4 'this is long variable a
.balign 4
.lcomm _Bi,4 'this is long variable b
.balign 4
.lcomm _Ci,4 'this is long variable c
.balign 4
.lcomm _Di,4 'this is long variable d
.balign 4
.lcomm _Ei,4 'this is long variable e
.balign 4
.lcomm _Fi,4 'this is long variable f
.balign 4
.lcomm _Gi,4 'this is long variable g
.balign 4
.lcomm _Hi,4 'this is long variable h
Like I said, without examining the actual FreeBasic routines, it is just a best
guess as to what the routines do (the names help) and what the parameters
on the stack represent. Since the IDA PRO disassembler converts the whole
EXE file back into ASM form, it can be useful for examining the various FB routines and seeing what they really do, how they work, and what the passed
parameters really represent.