flat assembler
Message board for the users of flat assembler.

Index > Main > [fasmg] 1f/1b type discardable labels?

Author
Thread Post new topic Reply to topic
Akeo



Joined: 19 Aug 2016
Posts: 8
Location: Ireland
Akeo 22 Sep 2016, 14:01
Maybe this is something that has been answered before (couldn't seem to find it when performing a search), but with some assemblers (e.g. gas), you can use short discardable labels within branches, of the form "<number>[f|b]" such as "1f" or "2b", that work as follows:

1. When the assembler encounters a '#f' label in a branch instruction, with # being a numeric value, it automatically looks forward (hence the 'f') for the next '#' numeric label in the assembly, and generate a branch to it
2. Likewise, when the assembler encounters a '#b' label in a branch instruction, it automatically looks backward for the last '#' numeric label and branch to it.

This means you can do stuff like the following, instead of having to come with more innovative ways to individually label stuff, which can be super convenient:
Code:
1:
  ... ; <section 0>
2:
  ... ; <section 1>
  tst <some condition1>
  bge 1f ; -> section 2
  bra 1b ; -> section 0
1:
  ... ; <section 2>
  tst <some condition2>
  beq 1f ; -> section 3
  bgt 2f ; -> section 4
  bra 2b ; -> section 1
1:
  ... ; <section 3>
2:
  ... ; <section 4>    
So I'm wondering how the same could be achieved in fasmg. I guess one could create a whole set of elements '1f', '2f', '3f', ..., '1b', 2b', '3b', ... with metadata that could resolve to a label (though not very convenient - what if someone wants to use '1234f' as a discardable branch label?), but then handling the labels themselves seems a bit tricky... So I'm wondering if someone has already looked into doing something like this.

Part of me also thinks that, since it's really super convenient, that it would be nice to have such a feature as some kind of native macro of fasmg (like 'sizeof' or 'scale'), that would resolve to the relevant address and that we could just call on when processing branch instructions...
Post 22 Sep 2016, 14:01
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20299
Location: In your JS exploiting you and your system
revolution 22 Sep 2016, 14:05
Use the dot (.):
Code:
function:
    ;..;
    .loop:    ;<--- make a label named function.loop
    ;...
    jnz .loop ;branch to label named function.loop    
Post 22 Sep 2016, 14:05
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20299
Location: In your JS exploiting you and your system
revolution 22 Sep 2016, 14:08
Oh, I missed the second question. for temporary forward and backward labels use @@, @f and @b:
Code:
@@:
 jmp @f
 jmp @b
@@:    
Post 22 Sep 2016, 14:08
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8349
Location: Kraków, Poland
Tomasz Grysztar 22 Sep 2016, 14:39
A simple macro that implements @@/@f/@b into fasmg is in the "Basic macros for fasmg" thread.

The same mechanic can be used to implement more levels (like @f1, @f2, etc.), or a separate sets of symbols could be created in parallel.

PS The name '1f' cannot be used for a symbol name, because it is a number, a floating-point one, to be exact.
Post 22 Sep 2016, 14:39
View user's profile Send private message Visit poster's website Reply with quote
Akeo



Joined: 19 Aug 2016
Posts: 8
Location: Ireland
Akeo 22 Sep 2016, 15:15
Aha, so that's called an "anonymous label". I guess I should have checked the basic macros thread first.

Thanks for the replies!
Post 22 Sep 2016, 15:15
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8349
Location: Kraków, Poland
Tomasz Grysztar 22 Sep 2016, 15:22
I'm going to present two possible ways of extending these basic macros. The fact that there are many "competing standards" (and that over the years people used to ask for various variants for fasm) was the main reason why I decided to leave it up to macros. And for non-tool-generated source codes the namespaces (like what revolution proposed in his first post) are in my opinion superior.

First method is to keep anonymous labels always named @@, but to allow jumping not only to the nearest ones with @b and @f, but also a bit further - for example @b2 and @f2 would to a second one in given direction. My sample defines it only up to @b3/@f3, and these definitions could be automated with "repeat" loop, but I kept it this simple so it is easier to visually parse what it does:
Code:
define @f @f1
define @ff @f2
define @b @b1
define @bb @b2

macro @@ tail
        match label, @f1?
                label tail
        end match
        local anonymous
        @b3? reequ @b2
        @b2? reequ @b1
        @b1? reequ @f1
        @f1? reequ @f2
        @f2? reequ @f3
        @f3? reequ anonymous
end macro

struc dummy
end struc
repeat 3
        @@ dummy
end repeat
purge dummy    
This variant is used like this:
Code:
        jmp     @f2     ; -> 2
@@: ; 1
        jmp     @b      ; -> 1
        jmp     @f2     ; -> 3
@@: ; 2
        jmp     @b2     ; -> 1
@@: ; 3
        jmp     @b3     ; -> 1    


The second variant allows to define multiple labels called @1, multiple ones called @2, etc. This time it @1f to jump to the nearest @1 forward, @1b to jump to the nearest @2 backward, and so on. The number of available label names can be tweaked by modifying the first line only:
Code:
repeat 10

        macro @#% tail
                match label, @#%#f?
                        label tail
                        @#%#b? equ @#%#f?
                end match
                local anonymous
                @#%#f? equ anonymous
        end macro

        define @#%#f?
        @#%

end repeat    
And here's an example usage for the second variant:
Code:
@1: ; a
        jmp     @1f     ; -> b
        jmp     @2f     ; -> c
        jmp     @1b     ; -> a
@1: ; b
        jmp     @1b     ; -> b
@2: ; c
        jmp     @2b     ; -> c
@1: ; d
        jmp     @1b     ; -> d    
Post 22 Sep 2016, 15:22
View user's profile Send private message Visit poster's website Reply with quote
Akeo



Joined: 19 Aug 2016
Posts: 8
Location: Ireland
Akeo 23 Sep 2016, 10:41
That second variant is pretty much exactly what I was looking for, so that's what I went with.

Thanks, as usual, for the awesome help! Wink
Post 23 Sep 2016, 10:41
View user's profile Send private message Visit poster's website Reply with quote
VEG



Joined: 06 Feb 2013
Posts: 80
Location: Minsk, Belarus
VEG 07 May 2017, 18:52
I have another idea of anonymous labels. We have numbered labels from @0 to @9. When we at @0, it means that we can jump only forward to @1 .. @9. When we at @5, we can jump backward to @0 .. @5, or forward to @6 .. @9. When we at @9, we can jump backward only (because there is no @10).

Basically, the idea is:
Code:
    ; it is possible to jump (only):
@0: ; backward to @0,       forward to @1 .. @9
@1: ; backward to @0 .. @1, forward to @2 .. @9
@2: ; backward to @0 .. @2, forward to @3 .. @9
@3: ; backward to @0 .. @3, forward to @4 .. @9
@4: ; backward to @0 .. @4, forward to @5 .. @9
@5: ; backward to @0 .. @5, forward to @6 .. @9
@6: ; backward to @0 .. @6, forward to @7 .. @9
@7: ; backward to @0 .. @7, forward to @8 .. @9
@8: ; backward to @0 .. @8, forward to @9
@9: ; backward to @0 .. @9, no forward labels
@0: ; backward to @0,       forward to @1 .. @9
@1: ; backward to @0 .. @1, forward to @2 .. @9
@2: ; backward to @0 .. @2, forward to @3 .. @9
@3: ; backward to @0 .. @3, forward to @4 .. @9
...    
How it looks like:
Code:
@0:
    ; @0 removes old labels @1 .. @9, so we can jump only forward here
    test eax, eax
    jz @5
@1:
    ; at this point we can jump backward to @0 or @1, or forward to @5 or @9
    mov eax, 500
    jmp @9
@5:
   ; at this point we can jump backward to @0, @1 or @5, or forward to @9
    mov eax, 100
@9:
    ; here we can jump only backward to @0, @1, @5 or @9
@0:
    ; here we can jump only forward to following @0 .. @9
...    
So, we can jump backward only to current or to labels with lower number, and we can jump forward only to labels with higher number. So, it is not required to write direction, because it is clear from a number.

The problem is here that it requires using macros @0 .. @9, and the same name required for "equ"s.

I've tried to write an experimental macro which will use the same name for a macro and for a "label".

It seems that it works nice with "define":
Code:
macro @0 tail
        if defined @0
                redefine @0 2
        else
                define @0 1
        end if
end macro
@0:
db @0
@0:
db @0    
Outputs: 0x01, 0x02, as expected. But I need to set @0 to an anonymous label, and I have to use "equ" for it, but I can't:
Code:
macro @0 tail
        @0 equ 1
end macro
@0:
db @0
@0:
db @0    
It seems, that "@0 equ 1" is treated as a call to the @0 macro, because @0 is on the first place of the line. So, there is an endless recursion.

Maybe it is better to allow to use "equ" in the same way as "define", like:
Code:
define @0 1
equ @0 1    

It seems that this difference in syntax was dictated by the FASM1. IMHO, it is better to use similar syntax for similar tasks. It seems that it is possible to extend syntax of the define itself for supporting of the equ behavior. For example, "define!" may work like the equ Smile

And yes, do you think that this idea is ok, or maybe it is better to refuse it, because it is not ok to use the same name for a macro and for an equ?


Last edited by VEG on 07 May 2017, 19:10; edited 1 time in total
Post 07 May 2017, 18:52
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8349
Location: Kraków, Poland
Tomasz Grysztar 07 May 2017, 19:09
VEG wrote:
But I need to set @0 to an anonymous label, and I have to use "equ" for it, but I can't
The only difference between EQU and DEFINE, just like in fasm 1, is that EQU does a single pass of replacement of symbolic variables in its value. You can do the same thing with MATCH+DEFINE.

VEG wrote:
Maybe it is better to allow to use "equ" in the same way as "define", like:
Code:
define @0 1
equ @0 1    
You can try it like this:
Code:
macro equ? statement&
        rawmatch name= raw_value, statement
                match value, raw_value
                        define name value
                else
                        define name
                end match
        else
                define statement
        end rawmatch
end macro     
Post 07 May 2017, 19:09
View user's profile Send private message Visit poster's website Reply with quote
VEG



Joined: 06 Feb 2013
Posts: 80
Location: Minsk, Belarus
VEG 07 May 2017, 19:21
Tomasz Grysztar, it works, thank you Smile
Post 07 May 2017, 19:21
View user's profile Send private message Visit poster's website Reply with quote
VEG



Joined: 06 Feb 2013
Posts: 80
Location: Minsk, Belarus
VEG 07 May 2017, 21:27
I've modified my first idea a bit. Every @@ resets @0..@9. So, there are own @0..@9 between @@ and @@, like local anonymous sublabels. @b and @f are still available, and they point to the nearest @@ labels as always before.
Code:
macro @@ tail
        match label, @f?
                label tail
                @b? equ @f?
        end match
        local anonymous
        @f? equ anonymous
        repeat 10, i:0
                local anonymous#i
                redefine @#i anonymous#i
        end repeat
end macro

define @f?
@@

repeat 10, i:0
        macro @#i tail
                match label, @#i
                        label tail
                end match
        end macro
end repeat    
Code:
; This example outputs these bytes, as expected: 1,2,3,4,4,6,7,8,9.

@@:
        db @1
@1:
        db @2
@2:
        db @f
@@:
        db @b
@1:
        db @2
@2:
        db @f
@@:
        db @1
@1:
        db @2
@2:
        db @3
@3:    

I've written it (based on the example by Tomasz Grysztar), it works, but I don't know how Smile This part of FASM macros is still pure magic for me. For example, I thought that equ will be required here, but it works only with redefine (redefine @#i anonymous#i) =) I'll try to read the FASM Manual again. Maybe I'll understand it better.


Last edited by VEG on 07 May 2017, 21:44; edited 1 time in total
Post 07 May 2017, 21:27
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8349
Location: Kraków, Poland
Tomasz Grysztar 07 May 2017, 21:38
VEG wrote:
I've written it (based on the example by Tomasz Grysztar), it works, but I don't know how Smile This part of FASM macros is still pure magic for me. For example, I thought that equ will be required here, but it works only with redefine (redefine @#i anonymous#i) =) I'll try to read the FASM Manual again. Maybe I'll understand it better.
DEFINE creates symbolic links just as well as EQU does. The only real difference between them is if the value given to EQU contains some symbols that are symbolic replacements themselves. And even then in many cases you may not notice the difference, because nested symbolic replacements happen anyway if you use such symbol in a final expression.
Post 07 May 2017, 21:38
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:  


< 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-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.