flat assembler
Message board for the users of flat assembler.

flat assembler > Windows > Learning fasm from masm

Goto page 1, 2, 3, 4, 5, 6  Next
Author
Thread Post new topic Reply to topic
nmake



Joined: 13 Sep 2012
Posts: 193
Hi people.

I am a masm32 guy and I wanted to try out fasm. I downloaded and installed it.

I was wondering if anyone could explain the different operators (the skeleton) of a fasm source file.

In the examples source file I noticed that you type the name of the functions you want to import, what method do you use to simplify this, I suppose it can get a little bit boring in the long run to type it manually?

Regards,
nmake Smile
Post 13 Sep 2012, 06:10
View user's profile Send private message Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
First off, welcome to the board.

FASM is a flat assembler. Whatever structure comes to your mind can be assembled by our lovely Fasm.


head on over to http://flatassembler.net and click the documentation. Also, the Fasm package it comes with a PDF manual.
Post 13 Sep 2012, 09:06
View user's profile Send private message Reply with quote
JohnFound



Joined: 16 Jun 2003
Posts: 3500
Location: Bulgaria
There are macro libraries automating the importing functions from libraries. (and many more things)
Read the FASM manual.
The simplest examples are written in "manual way" in order to not hide the details. In a real world project you will never have to do it manually.

Also, check http://fresh.flatassembler.net - FreshLib library uses slightly different macro syntax - more simple and IMHO more ASM-like.
Post 13 Sep 2012, 10:22
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1391
Location: Toronto, Canada
@nmake:
I moved to FASM from TASM (which has very close to MASM syntax).
Basically, the only thing I had to learn is to use square brackets properly.
In TASM for example:
Code:
Variable DD 6372h
...
MOV EAX, Variable                ; Load the contents of Variable
MOV EAX, OFFSET Variable     ; Load the adress of Variable
    

In FASM it goes like that:
Code:
MOV EAX, Variable                ; Load the adress of Variable
MOV EAX, [Variable]            ; Load the contents of Variable
    

As far as I recall - this is the only major thing that I had to remember.
There are a few other things different, like LOCAL vars definition.
Just get some small project to code in FASM and you'll be "moved" to FASM.
Also, macro language in FASM has some kinky stuff and a lot of it, but I
never learned all of it - just a very simple macros I needed.
Post 13 Sep 2012, 13:56
View user's profile Send private message Send e-mail Reply with quote
nmake



Joined: 13 Sep 2012
Posts: 193
Hi.

In the days of Dos I coded much TASM myself. Thanks for the replies, are there any other significant differences between fasm and masm that I need to be aware of?

I am reading the manual. Lots of nice innovation in fasm. Very Happy
Post 13 Sep 2012, 17:15
View user's profile Send private message Reply with quote
nmake



Joined: 13 Sep 2012
Posts: 193
I have been looking and reading, can anyone tell me what the usual approach is when you need to create a library, or simply store away code and reuse it, what is the most usual approach to this. My understanding is that fasm doesn't create libraries, you need an external linker for that.

How can I create my personal libraries (store away code and reuse it) without using an external linker?
Post 13 Sep 2012, 21:50
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4203
Location: 2018
fasm have a built-in linker.

you can create your dll with fasm, and link them using the import sections in your fasm wource code.

you can compile code using imports even if the dll don't exist, you just have to give the name of the dll, the names of functions to import, and make them correspond a label to use in your code.

from fasmw Dll example:
Code:

format PE GUI 4.0
entry start

include 'win32a.inc'

section '.text' code readable executable

  start:
        invoke  ShowLastError,HWND_DESKTOP
        invoke  ExitProcess,0

section '.idata' import data readable writeable

  library kernel,'KERNEL32.DLL',\
          errormsg,'ERRORMSG.DLL'

  import kernel,\
         ExitProcess,'ExitProcess'

  import errormsg,\
         ShowLastError,'ShowLastError'
    

you can compile it without the presence of ERRORMSG.DLL in the folder. Smile of course, it will not run.

just look the dll source and enjoy the (relative) simplicity:
Code:

; DLL creation example

format PE GUI 4.0 DLL
entry DllEntryPoint

include 'win32a.inc'

section '.text' code readable executable

proc DllEntryPoint hinstDLL,fdwReason,lpvReserved
        mov     eax,TRUE
        ret
endp

; VOID ShowErrorMessage(HWND hWnd,DWORD dwError);

proc ShowErrorMessage hWnd,dwError
  local lpBuffer:DWORD
        lea     eax,[lpBuffer]
        invoke  FormatMessage,FORMAT_MESSAGE_ALLOCATE_BUFFER+FORMAT_MESSAGE_FROM_SYSTEM,0,[dwError],LANG_NEUTRAL,eax,0,0
        invoke  MessageBox,[hWnd],[lpBuffer],NULL,MB_ICONERROR+MB_OK
        invoke  LocalFree,[lpBuffer]
        ret
endp

; VOID ShowLastError(HWND hWnd);

proc ShowLastError hWnd
        invoke  GetLastError
        stdcall ShowErrorMessage,[hWnd],eax
        ret
endp

section '.idata' import data readable writeable

  library kernel,'KERNEL32.DLL',\
          user,'USER32.DLL'

  import kernel,\
         GetLastError,'GetLastError',\
         SetLastError,'SetLastError',\
         FormatMessage,'FormatMessageA',\
         LocalFree,'LocalFree'

  import user,\
         MessageBox,'MessageBoxA'

section '.edata' export data readable

  export 'ERRORMSG.DLL',\
         ShowErrorMessage,'ShowErrorMessage',\
         ShowLastError,'ShowLastError'

section '.reloc' fixups data discardable        
    
Post 13 Sep 2012, 22:33
View user's profile Send private message Visit poster's website Reply with quote
nmake



Joined: 13 Sep 2012
Posts: 193
I see. Is dynamic linking the only way to reuse your old code?
Post 13 Sep 2012, 22:36
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4203
Location: 2018
you can include the source of your functions inside the source of your application too.
if you create a function set for anything, and want to embed them inside all your projects, you just have to include "yourfunctions.inc" in the code section, or in any sections.

as an include just insert the source where it is declared, you can even do that (based on the previous example:

winheader.inc
Code:
format PE GUI 4.0
entry start

include 'win32a.inc'

section '.text' code readable executable

  start:
    


application.asm:
Code:
include 'winheader.inc'
        invoke  ShowLastError,HWND_DESKTOP
        invoke  ExitProcess,0
include 'imports.inc'
    


imports.inc:
Code:
section '.idata' import data readable writeable

  library kernel,'KERNEL32.DLL',\
          errormsg,'ERRORMSG.DLL'

  import kernel,\
         ExitProcess,'ExitProcess'

  import errormsg,\
         ShowLastError,'ShowLastError'
    


and you can reuse your winheader.inc and imports.inc files in any other project.
Post 13 Sep 2012, 22:43
View user's profile Send private message Visit poster's website Reply with quote
nmake



Joined: 13 Sep 2012
Posts: 193
I suppose fasm will include the file directly into the source just at the spot I put the include directive. And it will copy and paste it without altering anything of it. Thanks for your reply. Smile

Some times it is not practical to use DLL's all the time, so that is why I am asking.

I have one more thing I am really wondering about, it is how you call procedures in fasm.

You have invoke (in masm you need a prototype to have it work). And you have invoke in fasm as well, but its a macro and not something built into fasm..

When I create private procedures, should I call them using stdcall or invoke?
Post 13 Sep 2012, 22:47
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4203
Location: 2018
the way you call a procedure (function) depends on the calling convention you use.

fasm proc are to be used with invoke because it's stdcall calling convention.

you can also invent your own calling convention, it is not a problem, or use the simpler calling convention:

Code:
...
func:
add eax,1
ret
...
mov eax,3
@@:
call func
sub eax,4 ;here, eax equal 0 the first time, and -3 the second time
je @b ;reloop the first time
...some more code ;it will run here the second time
...
    

and now, take your keyboard, run fasmw and edit/compile/run code until you get it Smile
Post 13 Sep 2012, 23:11
View user's profile Send private message Visit poster's website Reply with quote
JohnFound



Joined: 16 Jun 2003
Posts: 3500
Location: Bulgaria
For me the best way to reuse code in FASM is to put this code in the file and then to include it in your program.
Note, if you use FASM or FreshLib "proc" macros, the code of the procedure will be included in the compiled binary only if you use this procedure somewhere. This way, it is safe to pack multiply procedures in one source level library and to reuse it everywhere.

IMO, .obj files and linker should be used only when you need to link libraries written on other assembler or HLL.

All libraries of FreshLib are created this way and it is very useful approach.
Post 13 Sep 2012, 23:47
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
nmake



Joined: 13 Sep 2012
Posts: 193
Thanks all of you.

JohnFound: So if I put procedures, macros and even data in a source file, then include it in another source file, no procedures, macros or data will be part of the executable if I do not refer to any of the 3 mentioned?

If I create a procedure and put it in its own source file to be included later. Do I need to put .code operator and segments into that source file or is it enough to just put "name proc and endp" and the code?

Also, do I need to put my procedures at the top of the source file, before I actually call the procedures, or can I put it after the places where I refer and use the procedures? In Masm, you need to put it before you call it or else it will fail, unless you use prototypes.
Post 13 Sep 2012, 23:52
View user's profile Send private message Reply with quote
nmake



Joined: 13 Sep 2012
Posts: 193
Like this

name proc
ret
endp

invoke name (this works in masm)


however, this does not work unless you use prototypes:

invoke name

name proc
ret
endp
Post 13 Sep 2012, 23:55
View user's profile Send private message Reply with quote
JohnFound



Joined: 16 Jun 2003
Posts: 3500
Location: Bulgaria
nmake wrote:
Thanks all of you.
JohnFound: So if I put procedures, macros and even data in a source file, then include it in another source file, no procedures, macros or data will be part of the executable if I do not refer to any of the 3 mentioned?

It works only for code and data defined between "proc" and "endp".
For data definitions you should take care using conditional assembly:
Code:
if used MyData
  MyData db 1,2,3,0
end if
    

You can, of course, create your own macros for data definitions that to include these statements internally and then simply to invoke them in your program.

Quote:
If I create a procedure and put it in its own source file to be included later. Do I need to put .code operator and segments into that source file or is it enough to just put "name proc and endp" and the code?


"proc name" and "endp" actually. Smile
FASM is flat assembler. The code is generated in the order you include it in the source. But there is a workaround (using macros) - global data definition macros that will allow you to describe the data on random place in your source and then will define it grouped on one place - in the data section of the executable.

Quote:
Also, do I need to put my procedures at the top of the source file, before I actually call the procedures, or can I put it after the places where I refer and use the procedures?


You can define your code and every labels before or after you use them. No prototypes are needed. FASM makes multiply passes and resolves all dependencies automatically.

_________________
Tox ID: 48C0321ADDB2FE5F644BB5E3D58B0D58C35E5BCBC81D7CD333633FEDF1047914A534256478D9
Post 14 Sep 2012, 00:33
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
nmake



Joined: 13 Sep 2012
Posts: 193
Thanks.

I read about conditional preprocessing and the match directive in the documentation, but I did not understand it, the docs are too short for me to understand it. Could you bring me a simple example how to use the match directive? Preferably two small examples so I can compare them? Very Happy
Post 14 Sep 2012, 15:07
View user's profile Send private message Reply with quote
dancho



Joined: 06 Mar 2011
Posts: 74
here :
http://board.flatassembler.net/topic.php?t=4638

and search macroinstructions subforum...
Post 14 Sep 2012, 15:15
View user's profile Send private message Reply with quote
nmake



Joined: 13 Sep 2012
Posts: 193
Thanks, I think I understand it just a little bit, I have to test it to get a better grasp of it.

I am trying to display a numeric constant during assembling by using the display directive.

I do this:

MyNum = 10

Display MyNum does not work on constants, it translates it to ascii. How can I effectively print a constant as it is?

Also, do anyone know how I can keep track of build numbering, how many times I've built my program?
Post 14 Sep 2012, 19:19
View user's profile Send private message Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
nmake wrote:
I see. Is dynamic linking the only way to reuse your old code?


Like I said in my first post. Flat Assembler is able to output any kind of file structure you wish to make.

You can create object files too. Even image files (like .GIF) and sound files (.wav) from FASM.


"It only does everything"

Your mind is the limit here.
Post 14 Sep 2012, 21:09
View user's profile Send private message Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
nmake
Quote:
Display MyNum does not work on constants, it translates it to ascii. How can I effectively print a constant as it is?

The display directive prints only characters. If you try to display a numeric constant, then you get a character with the corresponding ASCII-code (like display 100 would display the character 'd').

To make it simple to display numbers, you need to redefine the display directive with a macro. I'm currently using the following macros specifically designed to be able to display any numeric constant representable in fasm:
Code:
;Displays a binary representation of a number
macro dispBin num*, padding, leader, trailer, size
{
 local digCount,number,lastdig
       number = size num
   lastdig = number

        if number < 0
            display '-'
               number = -(number shr 1 + number and 1)
             lastdig = -(lastdig + number + number)
      else
                number = number shr 1
               lastdig = lastdig and 1
     end if
      digCount = 0
        while number shr digCount > 0
            digCount = digCount + 1
     end while
   if ~ leader eq
              display leader
      end if
      if ~ padding eq
             if digCount < padding
                    times (padding-digCount-1) display '0'
            end if
      end if
      times digCount display number shr (digCount-%) and 1+'0'
  display lastdig+'0'
       if ~ trailer eq
             display trailer
     end if
}

;Displays a decimal representation of a number
macro dispDec num*, padding, leader, trailer
{
    local digCount,tenPow,number,lastdig
        number = num
        lastdig = number
    
    if number < 0
            display '-'
               number = (-(number shr 1 + number and 1)) / 5
               lastdig = -(lastdig + number*5 + number*5)
  else
                number = number/10
          lastdig = lastdig mod 10
    end if
      digCount = 0
        tenPow = 1
  while tenPow <= number
           tenPow = tenPow*10
          digCount = digCount + 1
     end while
   if ~ leader eq
              display leader
      end if
      if ~ padding eq
             if digCount < padding
                    times (padding-digCount-1) display '0'
            end if
      end if
      repeat digCount
             tenPow = tenPow/10
          display number/tenPow+'0'
         number = number mod tenPow
  end repeat
  display lastdig+'0'
       if ~ trailer eq
             display trailer
     end if
}

;Displays a hexadecimal representation of a number
macro dispHex num*, padding, leader, trailer, size
{
  local digCount,dig,number,lastdig
   number = size num
   lastdig = number
    
    if number < 0
            display '-'
               number = (-(number shr 1 + number and 1)) shr 3
             lastdig = -(lastdig + number shl 3 + number shl 3)
  else
                number = number shr 4
               lastdig = lastdig and 0xF
   end if
      digCount = 0
        while number shr (digCount*4) > 0
                digCount = digCount + 1
     end while
   if ~ leader eq
              display leader
      end if
      if ~ padding eq
             if digCount < padding
                    times (padding-digCount-1) display '0'
            end if
      end if
      repeat digCount
             dig = number shr ((digCount-%)*4) and 0Fh
           if dig > 9
                       dig = dig-'0'+('A'-10)
          end if
              display dig+'0'
   end repeat
  if lastdig > 9
           lastdig = lastdig-'0'+('A'-10)
  end if
      display lastdig+'0'
       if ~ trailer eq
             display trailer
     end if
}

;Displays a string with binary, decimal and hexadecimal values
;usage: display d=number,":",9,b=number,9,h=number,13,10
macro display [token]
{
     forward
             define matched +
            define matched -
            irp type, =b, =d, =h, =bb, =bw, =bd, =bq, =hb, =hw, =hd, =hq \{ match type==n,token \\{ restore matched \\} \}
            match =b==number,token \{ dispBin number,,,'b' \}
             match =d==number,token \{ dispDec number \}
             match =h==number,token \{ dispHex number,,'0x' \}
             match =bb==number,token \{ dispBin number,,,'b',byte \}
               match =bw==number,token \{ dispBin number,,,'b',word \}
               match =bd==number,token \{ dispBin number,,,'b',dword \}
              match =bq==number,token \{ dispBin number,,,'b',qword \}
              match =hb==number,token \{ dispHex number,,'0x',,byte \}
              match =hw==number,token \{ dispHex number,,'0x',,word \}
              match =hd==number,token \{ dispHex number,,'0x',,dword \}
             match =hq==number,token \{ dispHex number,,'0x',,qword \}
             match -,matched \{ display token \}
             match -,matched \{ restore matched \}
           restore matched
}    

The specifiers d, h and b define the representation radix, and using the modifiers b, w, d and q (combinable with the specifiers h and b) only affects the representation of the negative numbers.

Quote:
Also, do anyone know how I can keep track of build numbering, how many times I've built my program?

IMHO it's quite useless. An accidental compilation may affect the build number undesirebly. I'd prefer to use a manually specifiable (symbolic or numeric) constant at the beginning of the source code.

But if you still prefer to increment the build number automatically on each recompilation, you need to embed the counter into the binary you compile. Then you can open the previously produced binary with the file directive during the assembly stage of compilation and parse it with the load directive in order to find the embedded counter. I'd say, it's quite complicated for a beginner. However the clumsiness of the solution is comparable to the uselessness of the result. Wink
Post 14 Sep 2012, 21:59
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2, 3, 4, 5, 6  Next

< 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 © 1999-2019, Tomasz Grysztar.

Powered by rwasa.