flat assembler
Message board for the users of flat assembler.
Index
> Main > Virtual blocks, predictions, oscillation (?): how to fix? |
| Author |
|
|
revolution 05 Sep 2026, 15:44
The final virtual block is not needed. Change the first "virtual at MyLabel" to "virtual at ORIGIN" and delete the last three lines.
Alternatively if for some reason the extra virtual block is needed then move it up to the second line: Code: ORIGIN equ $81 virtual at ORIGIN MyLabel: end virtual virtual at MyLabel jmp Error Error: ; !!! Comment and uncomment this line !!! db 98 dup $01 if~($-ORIGIN<=100) 'Data is too large.' end if ; Display the number of bytes left until the fixed section limit is reached value?03=(100-($-ORIGIN)) if value?03<0 display '-' value?03=-value?03 end if sum?07=0 divisor?05=10'000'000'000'000'000'000 repeat 20 digit?06=(value?03/divisor?05)mod 10 divisor?05=divisor?05/10 if digit?06>0 display '0'+digit?06 else if sum?07|%=20 display '0' end if sum?07=sum?07+digit?06 end repeat end virtual |
|||
|
|
DimonSoft 05 Sep 2026, 16:07
Sorry, I might have reduced the code a bit too much.
In real code the second block contains some bytes before MyLabel (the variable-sized header), and after MyLabel the first virtual block contents are copied. So, the ORIGIN value is not really equal to MyLabel, MyLabel is greater by some value. Updated piece of code: Code: ORIGIN equ $81 virtual at MyLabel vbFirst:: jmp Error Error: ; !!! Comment and uncomment this line !!! ; db 98 dup $01 if~($-ORIGIN<=100) 'Data is too large.' end if ; Display the number of bytes left until the fixed section limit is reached value?03=(100-($-ORIGIN)) if value?03<0 display '-' value?03=-value?03 end if sum?07=0 divisor?05=10'000'000'000'000'000'000 repeat 20 digit?06=(value?03/divisor?05)mod 10 divisor?05=divisor?05/10 if digit?06>0 display '0'+digit?06 else if sum?07|%=20 display '0' end if sum?07=sum?07+digit?06 end repeat end virtual virtual at ORIGIN db 'Some bytes here' MyLabel: repeat ... ; Copying bytes from vbFirst end repeat end virtual So, removing the second block would require additional calculations instead of just relying on FASM to resolve it. The first version of the code makes the problem visible better by removing the details. |
|||
|
|
revolution 05 Sep 2026, 18:12
fasm is correct. The data is more than 100 bytes. The output shows -15 bytes remaining, i.e. 15 bytes too much.
|
|||
|
|
revolution 05 Sep 2026, 18:15
Maybe using $$ instead of ORIGIN is what is needed?
Code: ORIGIN equ $81 virtual at ORIGIN db 'Some bytes here' MyLabel: ;repeat ... ; Copying bytes from vbFirst ;end repeat end virtual virtual at MyLabel vbFirst:: jmp Error Error: ; !!! Comment and uncomment this line !!! db 98 dup $01 if~($-$$<=100) 'Data is too large.' end if ; Display the number of bytes left until the fixed section limit is reached value?03=(100-($-$$)) if value?03<0 display '-' value?03=-value?03 end if sum?07=0 divisor?05=10'000'000'000'000'000'000 repeat 20 digit?06=(value?03/divisor?05)mod 10 divisor?05=divisor?05/10 if digit?06>0 display '0'+digit?06 else if sum?07|%=20 display '0' end if sum?07=sum?07+digit?06 end repeat end virtual Code: flat assembler version 1.73.31 (16384 kilobytes memory) 0 2 passes, 0 bytes. |
|||
|
|
DimonSoft 05 Sep 2026, 20:10
As far as I understand, $$ is the origin of the closest nested virtual block, so in this case the suggested check is that vbFirst has at most 100 bytes. While the original check is that vbFirst will end before or at 100 bytes from ORIGIN-block, no matter what data prepends it in that block.
In the example with db 'Some bytes here' vbFirst should be limited to 100–15=85 bytes total, so that its last byte is no further than 100 bytes from ORIGIN. What really surprises me is that removing the if block with 'Data is too large' message with no other changes just make things work, except that the check is desired. Looks like depending on the presence of the check FASM calculates different offsets. I really can’t see how and why that happens. |
|||
|
|
DimonSoft 05 Sep 2026, 20:16
revolution wrote: fasm is correct. The data is more than 100 bytes. The output shows -15 bytes remaining, i.e. 15 bytes too much. It consists of “jmp +0” (2 bytes, right?) and 98 bytes produces by db. Now note that original code didn’t have the db 'Some bytes here' (so vbFirst data actually should have ended at 100 bytes offset in outer block), but still the check fired the error message. |
|||
|
|
revolution 06 Sep 2026, 01:33
DimonSoft wrote:
|
|||
|
|
DimonSoft 06 Sep 2026, 05:33
revolution wrote:
Only in the extended case. Remove the db and note that it’s still ”too large” in spite of being exactly 100 bytes. |
|||
|
|
revolution 06 Sep 2026, 05:49
DimonSoft wrote:
|
|||
|
|
DimonSoft 06 Sep 2026, 06:12
revolution wrote:
Please, move back to the code in the original post. The extended version was given just to show why I’m not willing to remove one of the virtual blocks. In the original code everything fits just fine, but the error message is still shown. |
|||
|
|
revolution 06 Sep 2026, 06:52
Oh, so the problem is the error message itself? Malformed instructions can't be resolved with multiple passes, so fasm will error out immediately as soon as it sees one.
That can be fixed by using a resolvable error: Code: rb -1 ; 'Data is too large.' ; <--- rb -1 can be resolved with multi-pass |
|||
|
|
DimonSoft 06 Sep 2026, 07:40
Well, not exactly the error message but the fact that it prevents FASM from doing the correct prediction and, yes, causes the compilation to fail immediately.
If I get it right, you suggest using something that is syntactically valid but causes error if the branch is finally selected. That might work but leaves another problem unsolved: the readable error message. For now the best way I found to get exactly the error message in the tiny FASMW error window is to put it in code as plain string literal, this ensures the message is shown complete and without other junk (like, say, err directive). rb -1 is not really useful for someone who uses the large macro set. |
|||
|
|
revolution 06 Sep 2026, 07:50
Then I think fasmw needs to be updated to show better outputs for errors. Because multi-pass resolution can give false values for forward referenced labels, so trying to always have if tests be correct in the presence of unknown future values is not possible in the general case. There is always the possibility that the if test will be wrong on an intermediate pass, but correct on the final pass.
fasm shows then entire line, including the comments and other trailing stuff. |
|||
|
|
revolution 06 Sep 2026, 08:39
Note there is also assert. It still has the same problem with the comment, but is a bit tidier than using if.
Code: assert $-ORIGIN<=100 ; 'Data is too large.' |
|||
|
|
DimonSoft 06 Sep 2026, 09:32
Actually, in the project itself the check is implemented as an assert macro that overrides the directive to allow custom error message
|
|||
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2026, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.