flat assembler
Message board for the users of flat assembler.
![]() Goto page 1, 2, 3, 4, 5, 6 Next |
Author |
|
typedef 13 Sep 2012, 09:06
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. |
|||
![]() |
|
JohnFound 13 Sep 2012, 10:22
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. |
|||
![]() |
|
AsmGuru62 13 Sep 2012, 13:56
@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. |
|||
![]() |
|
nmake 13 Sep 2012, 17:15
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. ![]() |
|||
![]() |
|
nmake 13 Sep 2012, 21:50
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? |
|||
![]() |
|
edfed 13 Sep 2012, 22:33
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. ![]() 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 |
|||
![]() |
|
nmake 13 Sep 2012, 22:36
I see. Is dynamic linking the only way to reuse your old code?
|
|||
![]() |
|
edfed 13 Sep 2012, 22:43
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. |
|||
![]() |
|
nmake 13 Sep 2012, 22:47
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.
![]() 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? |
|||
![]() |
|
edfed 13 Sep 2012, 23:11
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 ![]() |
|||
![]() |
|
JohnFound 13 Sep 2012, 23:47
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. |
|||
![]() |
|
nmake 13 Sep 2012, 23:52
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. |
|||
![]() |
|
nmake 13 Sep 2012, 23:55
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 |
|||
![]() |
|
JohnFound 14 Sep 2012, 00:33
nmake wrote: Thanks all of you. 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. ![]() 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 |
|||
![]() |
|
nmake 14 Sep 2012, 15:07
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? ![]() |
|||
![]() |
|
dancho 14 Sep 2012, 15:15
|
|||
![]() |
|
nmake 14 Sep 2012, 19:19
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? |
|||
![]() |
|
typedef 14 Sep 2012, 21:09
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. |
|||
![]() |
|
l_inc 14 Sep 2012, 21:59
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. ![]() |
|||
![]() |
|
Goto page 1, 2, 3, 4, 5, 6 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.