flat assembler
Message board for the users of flat assembler.

Index > Compiler Internals > size context of the [i]times[/i] argument value

Author
Thread Post new topic Reply to topic
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
As it is documented, the operators not, xor and shr work differently depending on the precision context. It does not seem however to be documented what context is valid for all the assembly directives, that take a numeric expression as an argument. E.g., the following code may have 3 different outcomes depending on the precision context:
Code:
times -(-1)shr 64 display 'Infinite precision',13,10    

a) If the precision is limited to 64 bits (or less), nothing is displayed. That's how it works now.
b) If the precision was infinite the string would be displayed exactly once.
c) If the precision was limited to a size larger than 64 bits, then the result would be negative and the compilation would fail.

The ambiguity applies to all other control directives able to evaluate numeric expressions, including repeat, if, virtual at, etc.
My question is whether I could rely on the currently applied 64 bits precision context, or is this still an undecided design question? Or am I just missing something from the documentation?


To justify the topic title here's a question related specifically to the times directive. It is documented to repeat an instruction passed to it as a second argument. In a context of assembly languages an instruction is normally understood as a CPU instruction. However here the term seems to be used in some wider sense, because even the first usage example demonstrates repeating of a data definition directive, which is (strictly speaking) not an instruction (mnemonic).
So what does the term mean here considering that the following fails to compile?
Code:
x = 1
times 3 x=x*7    

Or to show an even more obvious inconsistency, this is OK:
Code:
times 1 label y    

and this is not:
Code:
times 1 y:    

_________________
Faith is a superposition of knowledge and fallacy
Post 26 May 2014, 23:19
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17658
Location: In your JS exploiting you and your system
revolution
Currently fasm uses 65 bit numbers internally.

0xffffffffffffffff is distinct from -1.
Post 26 May 2014, 23:37
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
revolution
I know that, but internal number implementation has nothing to do with precision contexts. And currently the precision context of nearly all control directives is 64 bit, where 0xffffffffffffffff is the same as -1.

Note the difference:
Code:
y = -1 ;unlimited precision context
x =qword -1 ;64 bit precision context (same as 0xffffffffffffffff)    

_________________
Faith is a superposition of knowledge and fallacy
Post 26 May 2014, 23:50
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7795
Location: Kraków, Poland
Tomasz Grysztar
l_inc wrote:
As it is documented, the operators not, xor and shr work differently depending on the precision context. It does not seem however to be documented what context is valid for all the assembly directives, that take a numeric expression as an argument.
You are right, and this has not been documented. All the expressions of "count" type that go with control directives use the 64-bit context. Internally this is performed by the "get_count_value" method, and the count expressions include the ones used by TIMES, REPEAT, data reservation, DUP syntax for data definitions, ALIGN, file offset and count of bytes for FILE.
Old versions of fasm used the 32-bit context for count expressions, but some time after I implemented the support for x86-64 architecture I decided that it is better to use 64-bit context uniformly for all such arguments.

l_inc wrote:
To justify the topic title here's a question related specifically to the times directive. It is documented to repeat an instruction passed to it as a second argument. In a context of assembly languages an instruction is normally understood as a CPU instruction. However here the term seems to be used in some wider sense, because even the first usage example demonstrates repeating of a data definition directive, which is (strictly speaking) not an instruction (mnemonic).
So what does the term mean here considering that the following fails to compile?
Code:
x = 1
times 3 x=x*7    

Or to show an even more obvious inconsistency, this is OK:
Code:
times 1 label y    

and this is not:
Code:
times 1 y:    
The scheme that I used in designing fasm is that every line of assembly source consists of any number of labels (words ending with ":") and then the instruction - understood as any kind of directive recognized by assembler. In the first section of Understanding fasm you may notice that I actually consider instruction mnemonics to be the special kind of directives - the ones that tell the assembler to generate a machine code and put it at current position. I often did use the "directive" and "instruction" terms interchangeably, for specific subsets I think it's better to use formulations like "control directives", "x86 instructions", etc. (note that the "Control directives" section of the manual is a subsection of the "Instruction Set").

The rule is that only one instruction is allowed per line - so everything that follows the initial labels has to be one and only one directive/instruction. The exception from this rule is the TIMES directive, which allows an additional instruction as its operand (not label though!), and this exception can also be nested.

This scheme also applies to the preprocessing - the preprocessor directive can also follow a label (or a number of labels), like any other instruction:
Code:
a: macro x { db 7 }
b:c: x    


PS The classic structure of an assembly line, which I used in fasm's design, is:
[label:] instruction [operand] [;comment]
fasm allows multiple label fields per one line, but the rest is more or less standard.
Post 27 May 2014, 08:40
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: 17658
Location: In your JS exploiting you and your system
revolution
Tomasz Grysztar wrote:
... every line of assembly source consists of any number of labels (words ending with ":") and then ...
I didn't know that.

BTW; Did you miss the current bug report "Bug compiling 1.0e-317 floating-point number"?
http://board.flatassembler.net/topic.php?t=16769
Post 27 May 2014, 08:55
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7795
Location: Kraków, Poland
Tomasz Grysztar
revolution wrote:
BTW; Did you miss the current bug report "Bug compiling 1.0e-317 floating-point number"?
I did not miss it, but haven't yet started working on it.
Post 27 May 2014, 08:56
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
Tomasz Grysztar
Quote:
You are right, and this has not been documented

But the question was, why this is not documented. Just unintentionally or do you want to have a possibility to change that in the future (and endanger programs written before)? I'd like to know, if I can rely on that behaviour.

Quote:
and then the instruction - understood as any kind of directive recognized by assembler

I would accept this as is in the context of the times directive, if there were no exceptions resulting in "unexpected instruction" (in contrast to "illegal instruction" in case of numeric constant or label definition):
Code:
times 1 repeat 3
    display 'Hello',13,10
times 1 end repeat    

Or may be a more useful example:
Code:
x = 60
times 5 if x mod % = 0
    display 'x is divisible by an LCM of {2..5}',13,10
times 5 end if    

It may seem that times only accepts "instructions", that are not involved in multiline constructs, but there's again a counterexample:
Code:
times 1 virtual at $
    dd 5
times 1 end virtual    

So what "instructions" do actually belong to this mysterious subset of instructions, that can become an argument of times ?

_________________
Faith is a superposition of knowledge and fallacy
Post 27 May 2014, 11:49
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7795
Location: Kraków, Poland
Tomasz Grysztar
l_inc wrote:
I would accept this as is in the context of the times directive, if there were no exceptions resulting in "unexpected instruction" (in contrast to "illegal instruction" in case of numeric constant or label definition):
Code:
times 1 repeat 3
    display 'Hello',13,10
times 1 end repeat    

Or may be a more useful example:
Code:
x = 60
times 5 if x mod % = 0
    display 'x is divisible by an LCM of {2..5}',13,10
times 5 end if    

It may seem that times only accepts "instructions", that are not involved in multiline constructs, but there's again a counterexample:
Code:
times 1 virtual at $
    dd 5
times 1 end virtual    

So what "instructions" do actually belong to this mysterious subset of instructions, that can become an argument of times ?
This is actually an effect of a more complex mechanism that is related to the block directives. Currently fasm disallows many of the combinations between repetitions and conditionals, because their processing is optimized in a way that required an assumption that the are always properly nested and no overlapping occurs. For example:
Code:
repeat 1
 if 1
end repeat ; unexpected instruction
 end if    
This could be theoretically a valid construction, but current implementation disallows it. The same happens in this case:
Code:
while 1
 repeat 1
end while ; unexpected instruction
 end repeat    
In general, the "unexpected instruction" error marks the place where the nesting has been broken. For the same reason you cannot use the IF/REPEAT/WHILE in the operand for TIMES directive, because you cannot fit both the REPEAT and END REPEAT there, so it is impossible to properly nest one in the other (you may think of the operand for TIMES as a single-instruction block for REPEAT directive - so, for example, putting IF there is equivalent to the first example above).

This rule of proper nesting applies only to the directives that control the flow of the assembly - the repeats and conditional blocks. Section 2.2.3 of manual declares this to be the case for IF, REPEAT and WHILE (it's in the last paragraph) - I forgot to mention TIMES there, but it is just a different syntactical variant of REPEAT (one that makes further nesting impossible by its very nature). I should add additional line explaining it there.
Other block instructions, like VIRTUAL or DATA, do not need to follow such rules:
Code:
repeat 3
  virtual at %
end repeat
times 2 end virtual
end virtual    
Post 27 May 2014, 16:19
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7795
Location: Kraków, Poland
Tomasz Grysztar
l_inc wrote:
Tomasz Grysztar
Quote:
You are right, and this has not been documented

But the question was, why this is not documented. Just unintentionally or do you want to have a possibility to change that in the future (and endanger programs written before)? I'd like to know, if I can rely on that behaviour.
I did not document it, because I was not sure what the right choice for this context should be - and it was not really an important detail, so it stayed undefined. I doubt that I will change it, though - so I may as well write this down.
Post 27 May 2014, 16:27
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
Tomasz Grysztar
Quote:
This could be theoretically a valid construction, but current implementation disallows it.

Oh, that would be a huge mistake to allow such constructions. IMHO.

Aside from the natural ambiguity (is it a repetition of if 1 or is it a conditional end repeat?), no bizarre rules of evaluating this directive mixture would ever make it seep into a product of a tidy coder (I know: not an argument). However same is also true for my previous examples with times . I just wanted to know the limits of the formal applicability of times. Thank you for the clarification.

Quote:
I was not sure what the right choice for this context should be

Me neither, but if we try to nitpick here (yes, even more Smile), then this phrase:
Quote:
if the value specified by numerical expression has to fit in a unit of specified size, and the arguments for operation fit into that size, the operation will be performed with precision limited to that size

suggests to deduce an "otherwise not" meaning that the statement is an "if and only if".

This way I had a wrong expectation when trying to show off by converting this piece of code:
Code:
if iSize < 10
    display ' '
end if
;dispDec iSize    

into this one:
Code:
times -((iSize/10)-1)shr 64 display ' '
;dispDec iSize    

For the currently applied 64 bit precision a correct way could be:
Code:
times ((iSize/10)-1)shr 63 display ' '
;dispDec iSize    

The difference is very little, but it's still important, that the behaviour is defined in either way.

_________________
Faith is a superposition of knowledge and fallacy
Post 27 May 2014, 22:27
View user's profile Send private message 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-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.