flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
Tomasz Grysztar 22 Jan 2006, 14:55
You need to set up some constants at the very end of your source, that will summarize everything what happened before and define the values that can be forward-referenced from anywhere.
For example, let's consider that every jump to "alpha" label increases the "A" constant by 1 (starting with 0), and you need to know the final value at the time of "alpha" definiton. Here's how you can do it: Code: ; initial definitions A = 0 ; A starts counting from 0 macro jmp target { if target eq alpha A = A + 1 end if jmp target } macro .end { TOTAL = A } ; at the end of code we summarize gathered information ; start of code: jmp alpha ; A = 1 now label alpha display '0'+TOTAL ; here we need to know the total count jmp alpha ; A = 2 now jmp alpha ; A = 3 now .end ; end of code, the current value of A is used to define TOTAL The numerical constants can either be assembly-time variables, which cannot be forward-referenced, because they have changing value - assembler classifies them as such when at least one overloading happens during the whole assembly and the "A" constant in sample above is the example of such type - or they can be true constants, defined only once, and in such case assembler allows to forward-reference them (just like any labels) and resolves their value by multiple passes; the "TOTAL" in the sample above is such true constant. I see I need to put more into documentation about the numerical constants - it appears to be quite fasm-specific solution. |
|||
![]() |
|
Borsuc 22 Jan 2006, 15:08
thanks. So I need a "end" macro to do it, but how can I walk on a list at "end", say for each jmped label value (like A)? Or do I really need to append it to the list if it's not already there (via match and equ) and then, at "end" to use irp?
PS: Can I use Code: if ~ defined A A = 0 else A = A+1 instead of declaring A = 0 outside? because I really want it to be hidden from outside the macro. thanks again. ![]() |
|||
![]() |
|
Tomasz Grysztar 22 Jan 2006, 15:29
Yes, you would perhaps need to gather the whole list of labels and process it with "match". And the ".end"-like macro is required so you know when to summarize.
Defining a macro and providing the initialization of its variables, like "A=0" next to it, is a common technique and I don't know why would you like to do it other (less clean) way. The other solution would to put the initialization block inside the macro in the "match" block and use some additinal symbolic constant to ensure the initialization block will be invoked only the first time macro is used. The "defined" won't work this way - see 2.2.5. I'd recommend to not use it at all when it may cause any self-dependence. It was introduced, with "used" operator, to be applicable rather to the places like: Code: if defined WndProc ; when WndProc defined somewhere, here do some additional tasks end if |
|||
![]() |
|
Borsuc 22 Jan 2006, 15:44
Tomasz Grysztar wrote: Defining a macro and providing the initialization of its variables, like "A=0" next to it, is a common technique and I don't know why would you like to do it other (less clean) way. The other solution would to put the initialization block inside the macro in the "match" block and use some additinal symbolic constant to ensure the initialization block will be invoked only the first time macro is used. But I need a initialization (different names via concatenation) for each different label target (if the target has been encountered before, it will get incremented).. yeah, I guess the "match" and symbolic constant will work here. Tomasz Grysztar wrote: The "defined" won't work this way - see 2.2.5. I'd recommend to not use it at all when it may cause any self-dependence. It was introduced, with "used" operator, to be applicable rather to the places like: What's difference between "defined" and "used"? PS: ran into another small problem (I know I may be doing something wrong).. If I have Code: label X at bx+5 and I want to do Code: if X = bx+5 Code: if X eq bx+5 first one gives error, second doesn't work.. any way to do this? thx |
|||
![]() |
|
Tomasz Grysztar 22 Jan 2006, 16:00
The_Grey_Beast wrote: But I need a initialization (different names via concatenation) for each different label target (if the target has been encountered before, it will get incremented).. yeah, I guess the "match" and symbolic constant will work here. Then you can do the initialization for the each possible type just next to the macro defition. The_Grey_Beast wrote: What's difference between "defined" and "used"? Code: alpha: while second one detects things like: Code: dd alpha The_Grey_Beast wrote: PS: ran into another small problem (I know I may be doing something wrong).. If I have Well, actually I never before needed such thing, that's why I never though about it. The comparison operators work only with number, for the obvious reason that "bx+5>bp+0" would be undecidable by assembler. |
|||
![]() |
|
Borsuc 22 Jan 2006, 16:12
Tomasz Grysztar wrote: Then you can do the initialization for the each possible type just next to the macro defition. I don't think I understand, but I want something like this: (target#_A is used instead of A here, for different labels) Code: macro jmp target { match +, target#__A \{ target\#_A = target\#_A + 1 \} match =target#__A, target#__A \{ define target\#__A + target\#_A = 0 \} } Could you explain better, cuz I know there's better solution ![]() Tomasz Grysztar wrote: First one detects things like: thanks ![]() Tomasz Grysztar wrote: Well, actually I never before needed such thing, that's why I never though about it. The comparison operators work only with number, for the obvious reason that "bx+5>bp+0" would be undecidable by assembler. Okay, I'll try some other tricks then |
|||
![]() |
|
Tomasz Grysztar 22 Jan 2006, 16:17
Oh, I see, I did misunderstood you, even though you wrote it clearly: "for each different label target".
And actually I have misled you, this Code: if ~defined A A = 0 else A = A+1 end if is perfectly correct in this case, and is actually very good example of the correct use of "defined" operator - since the "A" is assembly-time variable, and cannot be forward-referenced, and "defined" checks for you whether it can be referenced from the place where you check. So when you check with "defined" just before it is defined for the first time, it cannot be yet access, and "defined" will always return false. I'm sorry, I was too fast replying, forget what I wrote above about this fact. ![]() Quote: Okay, I'll try some other tricks then Here's some trick that works: Code: macro if_labels_equal label1,label2 { local result,l,b1,b2 result = 1 virtual at 0 inc byte [label1] l: inc byte [label2] if $-l <> l result = 0 else repeat l load b1 byte from %-1 load b2 byte from l+%-1 if b1 <> b2 result = 0 end if end repeat end if end virtual if result } label X at bx+5 if_labels_equal X,bx+5 display '!' end if |
|||
![]() |
|
Borsuc 22 Jan 2006, 16:22
Tomasz Grysztar wrote: Oh, I see, I did misunderstood you, even though you wrote it clearly: "for each different label target". No problem ![]() Tomasz Grysztar wrote: Here's some trick that works: I'll check it out. Thanks Tomasz ![]() |
|||
![]() |
|
Tomasz Grysztar 22 Jan 2006, 18:09
PS. Actually the counting code should look more like this:
Code: if ~defined A A = 0 end if A = A+1 This way it will initialize correctly even when invoked only once. |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2023, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.