flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
fabbel 06 Oct 2025, 12:18
.. another was to put it: **any** code that is 'installed' after pospone directive will get executed at end of script, be it regular fasmg (macro) code / directives, or even alm code (even if part of enclosing calm inx)
|
|||
![]() |
|
Tomasz Grysztar 06 Oct 2025, 14:28
fabbel wrote: 1/ flat assembler manual wrote: The file is first searched for in the directory containing file which included it and when it is not found there, the search is continued in the directories specified in the environment variable called INCLUDE (the multiple paths separated with semicolons can be defined there, they will be searched in the same order as specified). If file was not found in any of these places, preprocessor looks for it in the directory containing the main source file (the one specified in command line). fabbel wrote: while playing with postpone for inspiration / see how to collaborate with it, I came to experience behavior of postpone that I was not expecting (but came to like / cope with) : I recall I briefly experimented with POSTPONE being a single-use macro (similarly to how it was implemented in the preprocessor of fasm 1), but implementing it as a control directive felt simpler and more elegant. |
|||
![]() |
|
fabbel 06 Oct 2025, 15:29
thx for feedback !
Regarding postpone, indeed, it is defined as a control directive in the manual... it is just that I initially didn't anticipate this kind of effect (even if now appreciate like it is ) ... just wanted to share experience really ... i mean control directives are - for me - associated with "regular code" (as opposed to alm code, mean typ. directive like 'repeat/end repeat', 'if/end if', ... cannot normally show up inside calm inx impl., while, conversly, alm can only appear between calminstruction... end calminstruction) ... so it just confused my understanding as I initially just didn't not expect postponed execution - even if directive - to be able to call/jump directly inside alm code w/o explicit switch to alm ... at some point while experimenting, I even thought that at end of script, postpone was starting again from initial postpone statement, thus re-executing the whole postpone override code again ... before I realized it is really the "intrinsic" postpone directive itself that is setting the point of exec at end of script - no matter what/where that is.... |
|||
![]() |
|
Tomasz Grysztar 06 Oct 2025, 18:11
The state of fasmg's control flow can be stored and resumed at any point. This is essential for things like CALM code calling a macro, which in turn may call another CALM instruction and so on. A simple example with REPEAT (another control directive) demonstrates that everything can be rewound:
Code: calminstruction demo asm repeat 3 display '!' end calminstruction demo end repeat What makes it especially tricky is the fact that CALM commands like DISPLAY do not obey the assembly state which for normal (textual) instructions determines whether to execute only the unconditional ones (like when REPEAT has 0 count, or IF has a false condition, or POSTPONE is executed during the normal assembly pass, which also puts it into this "skip block" mode). It makes these command essentially like unconditional instructions and this is what caused the message to show up twice in your example. |
|||
![]() |
|
fabbel 08 Oct 2025, 11:40
thx vm for that example !
... striking / tricky stuff indeed... but makes sense vs what I saw with postpone ... though imho, and maybe esp. bec such interactions betw calm and fasmg directives are indeed tricky, am still wondering, if this should not be better documented somehow ... in the manual, or maybe a note in your " Tricky stuff in fasmg" thread ... let u decide ofc - as u see fit ... typ. as in our in your example, you end up being able to control a calm loop using fasmg repeat directive i/o of the 'more normal' way inside calm like Code: compute _idx, 1 compute _max, 3 (...) @loop: (...) compute _idx, _idx + 1 check _idx > _max jno @loop reg. Quote:
=> I see your point and that makes perfect sense indeed.. but as I see, this is still mostly calling sub-macro / sub calm inx as 'complete' entities ... ... I mean, when I look at your demo example, and even if I understand it now, it still feels like a struggle in my mind, not to question * is the display '!' running once / atomic with execution of calminstruction demo ? * or is it actually taken 'unconditionally' as part of the generated repeat / end repeat block ? |
|||
![]() |
|
Tomasz Grysztar 08 Oct 2025, 13:16
Let me try to write down an explanation, I need something I could then use as a basis for additions to the documentation.
When a source text is assembled, every consecutive line is preprocessed and executed, and the execution of line's instruction is conditional, depending whether we are in "skip" mode, macro definition mode, or a regular assembly. Unconditional instructions are executed regardless of the mode. This applies also to macros. When a macro is called, every line from the text of that macro is preprocessed (with the fresh values of the local parameters) and executed. A control directive like REPEAT or WHILE (and also POSTPONE) is able to store the "source context", which points to a line in a macro or source file, and all its "parent lines" (the line that called this macro or included this source file, and so on). This allows to repeat the assembly of the block of source by simply rewinding the assembler back to where it were when the REPEAT block was first started. And if the block should not be assembled at all (when REPEAT has zero count or WHILE's condition is already false), the assembler is put into "skip mode". Now a CALM instruction is a special kind of macro, where instead of standard preprocessing there is an execution of CALM commands, and the commands may generate lines to be assembled. These lines are executed normally, just like if a regular macro generated them, but if the "source context" is stored, it remembers the place in the CALM code, the position of a command that assembled the line. If we rewind to this context, we are going to execute the remaining code inside the CALM instruction once more. And because CALM commands (the binary code, not ALM source) are always executed unconditionally, they are not affected by the "skip" mode. Thus after POSTPONE they are executed during the initial skipping of the block, but then also when the block gets actually assembled again. |
|||
![]() |
|
fabbel 08 Oct 2025, 13:36
... thx again & all clear now ! much appreciated !
... your last 2 posts may very well be published as some 'official' documentation as I was suggesting ... |
|||
![]() |
|
fabbel 08 Oct 2025, 13:45
.. last post sounds pretty good as the general explanation + prev one to illustrate with example
|
|||
![]() |
|
bitRAKE 09 Oct 2025, 04:32
Tomasz Grysztar wrote: I thought this should be compatible with fasm 1, which has it documented as follows: Code: @echo off REM include_order.cmd -- Test include path search order: REM (assumes fasmg in environment) setlocal mkdir io_file mkdir io_cwd mkdir io_env REM __SOURCE__ echo include 'io_file/test.inc' >test.asm REM __FILE__ echo include 'test_path.inc' >io_file/test.inc echo display '1' >io_file/test_path.inc echo display '2' >io_cwd/test_path.inc echo display '3' >io_env/test_path.inc echo display '4' >test_path.inc REM 1. __FILE__ path superceeds all others set "include=%~dp0io_env" pushd io_cwd fasmg -n ../test.asm del ..\io_file\test_path.inc pause REM 2. current working directory fasmg -n ../test.asm del test_path.inc pause REM 3. %include% environment variable paths fasmg -n ../test.asm set "include=" pause REM 4. __SOURCE__ path, command line file location fasmg -n ../test.asm popd del test del test.asm del test_path.inc del io_file\test.inc del io_env\test_path.inc rmdir io_file rmdir io_cwd rmdir io_env endlocal _________________ ¯\(°_o)/¯ AI may [not] have aided with the above reply. |
|||
![]() |
|
Tomasz Grysztar 09 Oct 2025, 05:27
That's the difference from fasm, it checks the current directory (the one from which they process was started, for example from command line).
|
|||
![]() |
|
bitRAKE 09 Oct 2025, 05:53
Yeah, that's clear, but your use of "also" means "in addition to"; but the reality is "instead of". The test makes the difference explicit.
|
|||
![]() |
|
Tomasz Grysztar 09 Oct 2025, 06:02
It's not "instead of", because fasm did not have any additional path there in the order before ones from the environment variable. That's why I phrased it this way.
I did not add that the other difference is that it does not do the final fallback like fasm, but that was just my quick initial response. I then wrote it down properly in fasmg's manual. |
|||
![]() |
|
bitRAKE 09 Oct 2025, 06:13
Quote: If file was not found in any of these places, preprocessor looks for it in the directory containing the main source file (the one specified in command line). |
|||
![]() |
|
Tomasz Grysztar 09 Oct 2025, 06:16
bitRAKE wrote:
|
|||
![]() |
|
bitRAKE 09 Oct 2025, 06:29
It's easy enough to run the test on fasm:
Code: flat assembler version 1.73.32 (1048576 kilobytes memory) 1 1 passes, 0 bytes. Press any key to continue . . . flat assembler version 1.73.32 (1048576 kilobytes memory) 3 1 passes, 0 bytes. Press any key to continue . . . flat assembler version 1.73.32 (1048576 kilobytes memory) 3 1 passes, 0 bytes. Press any key to continue . . . flat assembler version 1.73.32 (1048576 kilobytes memory) ../io_file/test.inc [1]: include 'test_path.inc' error: file not found. |
|||
![]() |
|
Tomasz Grysztar 09 Oct 2025, 06:48
Oh, I though that you were still referring to fasmg. I did not check whether fasm behaves according to its own documentation, I was focused on fasmg here.
But even if fasm checks current directory, it is still not the same as fasmg, because it does it after checking the environment, not before. I think at one point I deemed being able to override environment headers with current directory more useful than having it only be the last resort. Should I backport this decision to fasm? |
|||
![]() |
|
bitRAKE 09 Oct 2025, 07:47
Tomasz Grysztar wrote: I think at one point I deemed being able to override environment headers with current directory more useful than having it only be the last resort. Should I backport this decision to fasm? _________________ ¯\(°_o)/¯ AI may [not] have aided with the above reply. |
|||
![]() |
|
fabbel 13 Oct 2025, 13:40
Hi again, sry in advance for being picky again maybe... but just thinking file directive may also need some similar extra documentation... or does it always require full path to target ?
(... btw, unless mistaken this wasn't specified in fasm1 doc either...) |
|||
![]() |
|
fabbel 13 Oct 2025, 14:22
.. actually, by a second look at current doc + quick look at famsg source code, i kinda understand it does similar file lookup as done by include directive - except the %include% env variable part... Am I correct ?
|
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.