flat assembler
Message board for the users of flat assembler.
Index
> Macroinstructions > Global strings with fasmg |
Author |
|
Tomasz Grysztar 04 May 2018, 15:03
One of the frequently requested kinds of macros for fasm has been the ones that would allow to define string values throughout the code but gather them all in a single place in data section. Various solutions existed for fasm 1, but in the case of fasmg it became much simpler.
The most basic macro package for this purpose may look like this: Code: define GLOBSTR 1 virtual at GLOBSTR.baseaddr GLOBSTR.buffer:: end virtual struc GLOBSTR data& virtual GLOBSTR.buffer . db data end virtual end struc macro GLOBSTR.here GLOBSTR.baseaddr db GLOBSTR.data GLOBSTR.where := GLOBSTR.baseaddr end macro postpone virtual GLOBSTR.buffer load GLOBSTR.data:$-$$ from $$ end virtual if ~ defined GLOBSTR.where display 'Global string data has been placed automatically at the end of the executable.',13,10 display 'To place it elsewhere, use "GLOBSTR.here" macro in the intended location.',13,10 GLOBSTR.baseaddr db GLOBSTR.data end if end postpone Code: _my_string GLOBSTR "My string",0 The "fastcall" macro from the basic fasm-compatible Win64 headers uses a "fastcall?.inline_string" macro when a string is given as an argument to function call. This makes it easy to override the default behavior and make it use GLOBSTR instead of embedding the string between the instructions: Code: macro fastcall?.inline_string var local data match value, var data GLOBSTR value,0 end match redefine var data end macro However, fasm 1 also had some more advanced macros for this purpose, like the one that used Boyer-Moore-Hornspool algorithm to look for duplicate strings or even proper substrings to reuse. As fasm 1 and fasmg share a lot of the language used to make that macro, it can be very easily ported. Here is a conversion that fits into the same GLOBSTR framework as defined above: Code: define GLOBSTR 1 virtual at GLOBSTR.baseaddr GLOBSTR.buffer:: end virtual virtual at 0 GLOBSTR.chr_skips:: dd 256 dup ? end virtual struc GLOBSTR data& local buffer,size,a,b,c,p,skip,found virtual at 0 buffer:: db data size := $ end virtual repeat 256 store size:dword at GLOBSTR.chr_skips:(%-1)*4 end repeat repeat size-1 load a:byte from buffer:%-1 store size-%:dword at GLOBSTR.chr_skips:a*4 end repeat virtual GLOBSTR.buffer found = -1 p = 0 while p + size <= $-$$ c = size while c > 0 load a:byte from $$+p+c-1 load b:byte from buffer:c-1 if a <> b c = -1 break end if c = c - 1 end while if c = 0 found = p break else load a:byte from $$+p+size-1 load skip:dword from GLOBSTR.chr_skips:a*4 p = p + skip end if end while if found >= 0 label . at $$+found else . db data end if end virtual end struc macro GLOBSTR.here GLOBSTR.baseaddr db GLOBSTR.data GLOBSTR.where := GLOBSTR.baseaddr end macro postpone virtual GLOBSTR.buffer load GLOBSTR.data:$-$$ from $$ end virtual if ~ defined GLOBSTR.where display 'Global string data has been placed automatically at the end of the executable.',13,10 display 'To place it elsewhere, use "GLOBSTR.here" macro in the intended location.',13,10 GLOBSTR.baseaddr db GLOBSTR.data end if end postpone The same tricks could also be used to treat other kinds of data, not just strings, though the code looking for duplicates would need to pay attention to the possibility of having relocatable values in the data definitions. |
|||
04 May 2018, 15:03 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.