flat assembler
Message board for the users of flat assembler.

flat assembler > Macroinstructions > Simple listing macro for fasmg

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6862
Location: Kraków, Poland
Seeing the listing-like macros that people create for fasm 1, I was inspired to try something similar in fasmg and this is the result:
Code:
define Listing namespace Listing offset = $%% macro disphex number*,digits:8 repeat digits digit = ((number) shr ((%%-%) shl 2)) and 0Fh if digit < 10 display '0'+digit else display 'A'+digit-10 end if end repeat end macro end namespace macro ? line& line namespace Listing undefined_bytes = $% - $%% defined_bytes = $%% - offset if $ - undefined_bytes - defined_bytes < $$ defined_bytes = $ - undefined_bytes - $$ end if offset = $%% disphex offset-defined_bytes,8 display ': ' column = 0 while defined_bytes if column = 8 column = 0 display 13,10,' ' end if load data:byte from $ - undefined_bytes - defined_bytes disphex data,2 display ' ' defined_bytes = defined_bytes - 1 column = column + 1 end while repeat 8-column display ' ' end repeat display `line,13,10 end namespace end macro
This macro intercepts all the "regular" instructions and lists the bytes generated by each. It is best to include it after the instruction sets and other such headers are defined.

This works well with x86 examples, but not with the examples that use HEX output - there the formatting macros intercept the bytes generated by instructions and convert them into hex text. In that case some other variant of listing macros would be needed - perhaps displaying the actual addresses instead of file offsets, and the bytes generated by instruction regardless of whether they go into the final output or not.
Post 27 May 2016, 19:01
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
Nice and simple. fasm 1 is attractive in how puzzling it is to implement some things. fasmg is just too powerful for this and needs some more challenging tasks. Smile

_________________
Faith is a superposition of knowledge and fallacy
Post 27 May 2016, 22:26
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6862
Location: Kraków, Poland
Here's that slightly modified variant that displays assumed addresses instead of file offsets and shows bytes generated by instructions even when they are in a virtual block and do not go into output file:
Code:
define Listing namespace Listing base = $$ offset = $ macro disphex number*,digits:8 repeat digits digit = ((number) shr ((%%-%) shl 2)) and 0Fh if digit < 10 display '0'+digit else display 'A'+digit-10 end if end repeat end macro end namespace macro ? line& line namespace Listing if ~ $$ eq base base = $$ offset = $$ end if bytes = $ - offset if $ - bytes < $$ bytes = $ - $$ end if offset = $ disphex (offset scale 0)-bytes,8 display ': ' column = 0 while bytes > 0 if column = 8 column = 0 display 13,10,' ' end if load data:byte from $ - bytes disphex data,2 display ' ' bytes = bytes - 1 column = column + 1 end while repeat 8-column display ' ' end repeat display `line,13,10 end namespace end macro


Last edited by Tomasz Grysztar on 20 Sep 2016, 13:48; edited 1 time in total
Post 28 May 2016, 19:22
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
Tomasz Grysztar
Quote:
shows bytes generated by instructions even when they are in a virtual block and do not go into output file

Which is in most cases not desirable actually. For that reason I explicitly omitted everything placed in nested virtual blocks, while allowing to display their internal content when additionally placing the ilen_/_ilen block inside. But in your case you also handle the virtual blocks incorrectly, because changing the addressing space does not necessarily mean setting current offset to the new base:
Code:
00401000: B8 00 00 00 00 mov eax,0 00401005: virtual 00401005: B8 01 00 00 00 mov eax,1 00401000: B8 00 00 00 00 end virtual ;<- All of a sudden 00401005: B8 02 00 00 00 mov eax,2


This approach has also another disadvantage: the instructions are not shown if they are generated by a higher-level macro such as invoke. This results in longer byte sequences without providing a good reference to what these refer to.

_________________
Faith is a superposition of knowledge and fallacy
Post 29 May 2016, 00:20
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6862
Location: Kraków, Poland
l_inc wrote:
Tomasz Grysztar
Quote:
shows bytes generated by instructions even when they are in a virtual block and do not go into output file

Which is in most cases not desirable actually. For that reason I explicitly omitted everything placed in nested virtual blocks, while allowing to display their internal content when additionally placing the ilen_/_ilen block inside.
The purpose of this second variant was noted in the first post - it is something that works with the examples that use the HEX output. The detection of changing addressing areas is very crude and flawed for the reasons you mentioned, but still this simple modification manages quite well to show the instruction codes.
Post 29 May 2016, 07:22
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
Tomasz Grysztar
Quote:
The purpose of this second variant was noted in the first post

Sorry, I missed that part. But the idea I tried to express is still same: it's better to use block-wise application of whatever effects. Nested blocks allow to differentiate what effect should be applied first. If done right, works quite well.

For example, the implementation of HEX.seg/HEX.endseg is problematic: to allow for nesting I always used in-place modification (needs improvement for compression cases) instead of enclosing into virtual-blocks. The org-directive however is a pain in the ass, and in early implementations I used the same close-reopen-block trick in an org-redefinition, but many encodings (e.g., into base64) are very hard to do that way, and supporting nesting requires to do all paired macros of such "encoding"-kind in a uniform way. So I switched to a different approach: all the data across all addressing spaces separated by the org directive are gathered into a single virtual-block, then converted using whatever encoding, then stored back overwriting the original bytes.

_________________
Faith is a superposition of knowledge and fallacy
Post 29 May 2016, 22:36
View user's profile Send private message Reply with quote
jmg



Joined: 18 Sep 2016
Posts: 62
Tomasz Grysztar wrote:
Here's that slightly modified variant that displays assumed addresses instead of file offsets and shows bytes generated by instructions even when they are in a virtual block and do not go into output file:


This is cool, but there were no actual usage examples ?

I played around by drop of the above into listing.inc & then
Code:
include 'listing.inc'

and that seems to generate a listing in the console, needing this for a file

Code:
..\..\fasmg invert.asm invert.bin > invert.lst


I notice that seems to go a little strange if
Code:
include 'hex.inc'

is also active - ie it seems designed for BIN output only?
or is there a include order or placement that works better with HEX ?

addit: Testing this, I see it appends this at end of list, on a pass

2 passes, 95 bytes.

and appends nothing on an asm fail, which is a little vague.

Can Fasmg instead list the Errors, so the LST file says either of

2 passes, 95 bytes. 0 Errors.
or
3 Errors.

It seems to not report the errors in the list file ? - I'm not sure how easy that is to add ?
Post 18 Sep 2016, 22:59
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6862
Location: Kraków, Poland
jmg wrote:
or is there a include order or placement that works better with HEX ?
At the end of my first post I explained that it does not work with HEX. The other variant of macro (in my second post) addresses this problem.

Quote:
It seems to not report the errors in the list file ? - I'm not sure how easy that is to add ?
The information about errors goes to stderr, while the one made by "display" goes to stdout.
Post 19 Sep 2016, 07:40
View user's profile Send private message Visit poster's website Reply with quote
jmg



Joined: 18 Sep 2016
Posts: 62
Tomasz Grysztar wrote:
jmg wrote:
or is there a include order or placement that works better with HEX ?
At the end of my first post I explained that it does not work with HEX. The other variant of macro (in my second post) addresses this problem.


That 2nd one, was the one I used for the tests.
It seems to do the listing part ok, but then appends some extra garbage, when HEX is enabled ?
Post 19 Sep 2016, 08:49
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6862
Location: Kraków, Poland
jmg wrote:
That 2nd one, was the one I used for the tests.
It seems to do the listing part ok, but then appends some extra garbage, when HEX is enabled ?
It shows the bytes generated by the HEX macro itself (the macro converts the instruction bytes from virtual blocks into HEX format and writes this into output with DB). You could turn off the listing macro before HEX finisher jumps in by adding these few lines into listing.inc:
Code:
postpone purge ? end postpone
But you need to make sure that listing.inc is included after hex.inc, because postponed block are executed from the last to first (and this way you also ensure that the not-postponed lines from hex.inc are not included in listing, either).

Because the macro does not differentiate what lines does it show, if you want all the lines from hex.inc to be ignored you may also modify the HEX macros themselves and make them generate listing of the code-related lines (this could be a "HEX with listing" macro package). Or even this simple trick could do the job:
Code:
macro ? line& line if __FILE__ <> 'hex.inc' ; <<< additional condition namespace Listing if ~ $$ eq base ; ... end namespace end if end macro
but when hex.inc is not in current directory, __FILE__ is going to contain the complete path and this won't work without some added processing.
Post 19 Sep 2016, 09:30
View user's profile Send private message Visit poster's website Reply with quote
shoorick



Joined: 25 Feb 2005
Posts: 1603
Location: Ukraine
I've got a lot of garbage, seems, because of macro "proc" (maybe because of semicolon after .end):
Code:
... 0000000F: C3 00 C8 jmp 0C800h 00000012: restore proc 00000012: define proc 1 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: a2im equ ma2i 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: .end: 00000012: proc negh 00000012: 7C mov a,h ...
-- I think, a feature to explicitly block the line against output into the listing would be enough.

_________________
UNICODE forever!
Post 20 Sep 2016, 09:48
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6862
Location: Kraków, Poland
This looks very strange. What is your "proc" macro like?
Post 20 Sep 2016, 10:02
View user's profile Send private message Visit poster's website Reply with quote
shoorick



Joined: 25 Feb 2005
Posts: 1603
Location: Ukraine
Code:
if ~ defined proc restore proc define proc 1 macro proc name name: if used name end macro macro endp! end if .end: end macro end if

(seems I took wrong variant)
Post 20 Sep 2016, 10:15
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6862
Location: Kraków, Poland
Oh I see, this is because procs are not included when not used, but ".end:" gets processed for each one since it is outside of "if used" (does it need to be outside?).

Anyway, you could modify the listing macros in some way like this:
Code:
Listing? = 1 namespace Listing base = $$ offset = $ macro disphex number*,digits:8 repeat digits digit = ((number) shr ((%%-%) shl 2)) and 0Fh if digit < 10 display '0'+digit else display 'A'+digit-10 end if end repeat end macro end namespace macro ? line& match =no? =listing?, line Listing? =: 0 else match =listing? =back?, line restore Listing? else line if Listing namespace Listing if ~ $$ eq base base = $$ offset = $$ end if bytes = $ - offset if $ - bytes < $$ bytes = $ - $$ end if offset = $ disphex (offset scale 0)-bytes,8 display ': ' column = 0 while bytes > 0 if column = 8 column = 0 display 13,10,' ' end if load data:byte from $ - bytes disphex data,2 display ' ' bytes = bytes - 1 column = column + 1 end while repeat 8-column display ' ' end repeat display `line,13,10 end namespace end if end match end macro
Then put "no listing" before the lines you don't want listed and "listing back" after them.


Last edited by Tomasz Grysztar on 20 Sep 2016, 13:49; edited 1 time in total
Post 20 Sep 2016, 10:34
View user's profile Send private message Visit poster's website Reply with quote
shoorick



Joined: 25 Feb 2005
Posts: 1603
Location: Ukraine
maybe something more simple?
i mean more standard single word switch, like NOLIST / LIST in other assemblers
Post 20 Sep 2016, 10:45
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6862
Location: Kraków, Poland
Modify it however you wish. Wink
Post 20 Sep 2016, 10:53
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6862
Location: Kraków, Poland
Apparently this variant of listing.inc does not work well with such "proc" anyway, because "proc" is not an unconditional macro (so it becomes a line processed by listing macro) but it opens "if" block without closing it - and this variant of listing macro tries to execute original line inside the "else" block, thus creating an overlapping of the control blocks, which leads to errors.

Here is a corrected variant that still executes the line outside of the control blocks. Some additional dummy macros are needed.

EDIT: updated with some additional improvements.
Code:
Listing? = 1 namespace Listing base = $$ offset = $ virtual at 0 HexDigits:: db '0123456789ABCDEF' end virtual end namespace macro ? line& line rmatch =nolist?, line Listing? =: 0 else rmatch =list?, line restore Listing? else if Listing namespace Listing if ~ $$ eq base base = $$ offset = $$ end if bytes = $ - offset if $ - bytes < $$ bytes = $ - $$ end if offset = $ address = (offset scale 0)-bytes repeat 8 load digit:byte from HexDigits:((address) shr ((%%-%) shl 2)) and 0Fh display digit end repeat display ': ' if bytes < 0 bytes = 0 end if while bytes > 0 if bytes > 8 load data:8 from $ - bytes repeat 8 load digit:byte from HexDigits:(data shr ((%-1) shl 3 + 4)) and 0Fh display digit load digit:byte from HexDigits:(data shr ((%-1) shl 3)) and 0Fh display digit,' ' end repeat bytes = bytes - 8 display 13,10,' ' else load data:bytes from $ - bytes repeat bytes load digit:byte from HexDigits:(data shr ((%-1) shl 3 + 4)) and 0Fh display digit load digit:byte from HexDigits:(data shr ((%-1) shl 3)) and 0Fh display digit,' ' end repeat break end if end while repeat 8-bytes display ' ' end repeat display `line,13,10 end namespace end if end rmatch end macro macro nolist? end macro macro list? end macro postpone nolist end postpone


Last edited by Tomasz Grysztar on 18 Oct 2016, 20:48; edited 5 times in total
Post 20 Sep 2016, 15:29
View user's profile Send private message Visit poster's website Reply with quote
jmg



Joined: 18 Sep 2016
Posts: 62
Tomasz Grysztar wrote:
Apparently this variant of listing.inc does not work well with such "proc" anyway, because "proc" is not an unconditional macro (so it becomes a line processed by listing macro) but it opens "if" block without closing it - ...


? Isn't that normally considered an error ?
Most pgms I use, get rather upset if they hit unbalanced blocks, as usually that is a user-typo.
Post 20 Sep 2016, 21:01
View user's profile Send private message Reply with quote
shoorick



Joined: 25 Feb 2005
Posts: 1603
Location: Ukraine
Yes, it's working, but I have added macros list/nolist to proc.inc also (inside if block to not clone lot of them), to not generate error if any other project do not use listing.
Post 21 Sep 2016, 02:48
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6862
Location: Kraków, Poland
jmg wrote:
Tomasz Grysztar wrote:
Apparently this variant of listing.inc does not work well with such "proc" anyway, because "proc" is not an unconditional macro (so it becomes a line processed by listing macro) but it opens "if" block without closing it - ...


? Isn't that normally considered an error ?
Most pgms I use, get rather upset if they hit unbalanced blocks, as usually that is a user-typo.
Yes, this is exactly what caused the problem here, the control blocks must be nested properly, so after "if" fasm was awaiting "end if" before the "match" block got closed.
Post 21 Sep 2016, 06:22
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  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 © 2004-2018, Tomasz Grysztar.

Powered by rwasa.