Reason for the Topic Split

Started by Donald Darden, June 14, 2007, 11:42:56 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Donald Darden

Writing Assembly Code is often quite involved.  To do it well, you really need to
focus on the machine design, and study techniques in coding that work well.  It
deserves its own forum.

But when coupled with FreeBASIC, PowerBASIC, or any other high end language,
you also need to consider the nature of that language and the additiional layered
concepts and constraints being imposed on you.  The same with the operating
system and device interfaces that you encounter.  These all mean departures and areas of separate exploration.

For the moment, I have decided to set up three forums for Assembly language,
one for the topic in general, and one each for particulars when using Assembly
with either FreeBasic or PowerBasic.  PowerBasic is an obvious choice for some of us, as being our area of prime interest when it comes to software development under Windows.  FreeBasic is less obvious, but presently a good alternative because it supports a similar syntax, and also works under Linux.

Depending upon your viewpoint, Assembly is either overrated or underutilized.
Having its own forums will give you a better chance to decide which is most true.

Charles Pegge

You will find that the Freebasic and Powerbasic assemblers and way in which they interface the basic language are very similar indeed and it is possible to write assembly code compatible with both with little more than adding '!' befor each PB assembler statement or putting your code into an ASM .. END ASM block for freebasic.

There are of course significant differences you need to be aware of and as I hop from one to the other quite frequently I can report the differences as they show up.

For instance when passing blocks of data in multidimensional arrays, you will find that FB and PB order their dimensions in opposite directions. so DIM a(99,1)  AS LONG  in Freebasic gives you 100 sets of 2 long integers arranged contiguously whereas PB expresses this oppositely: DIM a(1,99) AS AS LONG.

Generally speaking, I think it is a good idea to pass parameters to assembler functions byval rather than byref. So you don't have to decode the ref in the assembler function, and if you are passing a block of data or a static string or a dynamic string, it is very clear that you are passing a pointer when you use varptr() or strptr(). This is also useful if you intend porting your code to C or C++, where data is passed by value.

Donald Darden

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
print "a ="; a
asm mov al,al

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.