flat assembler
Message board for the users of flat assembler.

Index > Compiler Internals > virtual trouble | assert directive

Author
Thread Post new topic Reply to topic
DOS386



Joined: 08 Dec 2006
Posts: 1900
DOS386 19 Nov 2011, 08:04
Code:
format binary as "XXX"
use16
org 0

virtual at $1000
  xx2: db ?
  ; xxx: db ?
  xx3: db ?
  xx4: db ?
end virtual

virtual at bx
  bx2: db ?
  ; bxx: db ?
  bx3: db ?
  bx4: db ?
end virtual

mov ax, 0

mov [xx4], al
mov [xx2], ax ; ZERO'ize both "xx2" and "xx3"
mov [xx4], ax ; BUG but fine for the compiler

if ((xx2+1)<>xx3)
 err "(xx2+1)<>xx3"
end if

mov [bx4], al
mov [bx2], ax ; ZERO'ize both "bx2" and "bx3"
mov [bx4], ax ; BUG but fine for the compiler

; if ((bx2+1)<>bx3)
;  err "(bx2+1)<>bx3"
; end if
    


1. Line err "(xx2+1)<>xx3" should break the compilation if I uncomment xxx: db ? -> OK

2. Line err "(bx2+1)<>bx3" should break the compilation (only) if I uncomment bxx: db ? -> doesn't work, it breaks it always Sad

Any idea how to fix ?

EDIT by DOS386 2011-11-23 : enhanced subject, sticked, moved from Main into Compiler Internals

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug


Last edited by DOS386 on 23 Nov 2011, 13:40; edited 1 time in total
Post 19 Nov 2011, 08:04
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8353
Location: Kraków, Poland
Tomasz Grysztar 20 Nov 2011, 01:11
fasm's operators like "<", ">" or "<>" work only on numerical values, so if values are register-based, you get and error (that's because comparing register-relative addresses usually cannot be done at compile time). It may be possible to extend "<>" operator to detect the case when two expressions are based on the same register, but anyway - you can very easily get around this fasm's limitation:
Code:
 if ((bx2+1)-bx3<>0)
  err "(bx2+1)<>bx3"
 end if    
This works because by substracting two expressions based on the same register, you get numerical value, which then can be compared with "<>" or even ">" operators.
Post 20 Nov 2011, 01:11
View user's profile Send private message Visit poster's website Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1900
DOS386 20 Nov 2011, 01:28
Thanks Smile

BTW, a suggestion:

add a directive assert

Code:
assert (bx2+1-bx3=0)    


do nothing if condition true, break at this line if false Wink
Post 20 Nov 2011, 01:28
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8353
Location: Kraków, Poland
Tomasz Grysztar 20 Nov 2011, 01:31
Hmm, and this would be a recoverable error (as opposed to ERR directive, which is unrecoverable), signalized only when assertion fails consistently even when all other code is already resolved. This seems to be a nice idea.
Post 20 Nov 2011, 01:31
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc 23 Nov 2011, 00:35
Tomasz Grysztar
Quote:
This seems to be a nice idea.

Why make an additional compiler directive, if the same can be easily achieved with macros?
Code:
macro assert [expr]
{
       common
              if ~(expr)
                  display 'Error: assertion failed',13,10
                       rb -1
               end if
}    

For the same reason I never understood why the irp directive exists:
Code:
macro irpm [value]
{
        ;do something
}
irpm x,y,z    

has the same effect as
Code:
irp value,x,y,z
{
 ;do something
}    
Post 23 Nov 2011, 00:35
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8353
Location: Kraków, Poland
Tomasz Grysztar 23 Nov 2011, 11:21
l_inc wrote:
Why make an additional compiler directive, if the same can be easily achieved with macros?
Code:
macro assert [expr]
{
   common
              if ~(expr)
                  display 'Error: assertion failed',13,10
                       rb -1
               end if
}    
Because I feel there is some lack of symmetry that we have ERR directive to cause immediate error, but no similar directive suitable for checking the resolved value. "rb -1" is an idiom which requires additional knowledge that it causes "recoverable" error, and thus it needs to be documented. So having a nice "assert" directive instead of having to document behavior of some cryptic idiom seems to be a good thing, especially since this directive would be so cheap in implementation.

PS And IRP is there just because TASM had it. There is a number of TASM-inspired features here and there in fasm.
Post 23 Nov 2011, 11:21
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc 23 Nov 2011, 11:54
Tomasz Grysztar
Well. Fair enough. Thanks for the explanation. However rb -1 is already documented as a directive, causing a recoverable error:
Quote:
If it's needed to stop the assembly only when the condition is permanent, and not just occuring in the intermediate assembly passes, the trick with rb -1 can be used instead. The rb directive does not cause an error when it is provided with negative value in the intermediate passes.

Thus "additional knowledge" stems from the manual as it's usual for any knowledge.
Post 23 Nov 2011, 11:54
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8353
Location: Kraków, Poland
Tomasz Grysztar 23 Nov 2011, 12:01
I had to put it into documentation to mandate the use of this feature - but if there was some dedicated directive for that purpose, I would not have to document the "trick".
Post 23 Nov 2011, 12:01
View user's profile Send private message Visit poster's website Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1900
DOS386 23 Nov 2011, 13:37
l_inc wrote:
Code:
macro assert [expr]
{
      common
              if ~(expr)
                  display 'Error: assertion failed',13,10
                       rb -1
               end if
}    


You macro doesn't show the offending condition.

Of course, even better, assert could display the values involved in the false expression.

Code:
assert (bx2+1-bx3=0)
    


Code:
Assert directive, condition is false, bx2 is "bp+4", bx3 is "bp+6"
    

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 23 Nov 2011, 13:37
View user's profile Send private message Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc 23 Nov 2011, 14:49
DOS386
Quote:
You macro doesn't show the offending condition.

Firstly, this requirement was not included into the original scope statement. And unfortunately I'm not good enough in telepathy to guess it.
Secondly, the macro is very easily extendable to satisfy this requirement.
Quote:
even better, assert could display the values involved in the false expression

I don't think it's always possible to do in a reasonable way, because assert as directive should be processed within assembly stage, but the statement at this stage may contain preprocessed parts, that will not match the original syntactical representation of the statement, which makes displaying of the values impractical.
Post 23 Nov 2011, 14:49
View user's profile Send private message Reply with quote
mike.dld



Joined: 03 Oct 2003
Posts: 235
Location: Belarus, Minsk
mike.dld 18 Dec 2011, 10:22
I'm now using a macro similar to one l_inc provided, though a bit different one:
Code:
macro static_assert cond, message
{
  local ..static_assert_pass
  if defined ..static_assert_pass & ~ (cond)
    if ~ message eq
      display "Assertion failed: ", message, 13, 10
    end if
    err
  end if
  ..static_assert_pass:
}    

I had to use the trick with `defined` since values used in expression aren't necessarily correct right away, causing expression to evaluate to false when it actually is a truly one. So I guess I could second Tomasz on a need of support from assembler side to do this stuff.
Post 18 Dec 2011, 10:22
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8353
Location: Kraków, Poland
Tomasz Grysztar 11 Feb 2012, 19:09
The "assert" has been added in 1.69.36 release.
Post 11 Feb 2012, 19:09
View user's profile Send private message Visit poster's website Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1900
DOS386 19 Feb 2012, 08:44
Tomasz Grysztar wrote:
The "assert" has been added in 1.69.36 release.


Image

COOL Smile

PS: 37 is obsolete, get >= 38

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 19 Feb 2012, 08:44
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8353
Location: Kraków, Poland
Tomasz Grysztar 19 Feb 2012, 13:05
What I forgot to mention in 1.69.37 release notes is that I also improved "=" and "<>" operators so that they are able to compare any label values provided that both expressions have the same base (the thing you check with the new "relativeto" operator). It means that with latest releases the code from your first post is assembled without a complaint (and you can also change it to use "assert" instead of "if"+"err").
Post 19 Feb 2012, 13:05
View user's profile Send private message Visit poster's website Reply with quote
mike.dld



Joined: 03 Oct 2003
Posts: 235
Location: Belarus, Minsk
mike.dld 22 Feb 2012, 05:40
Thanks, Tomasz, it works great.
Post 22 Feb 2012, 05:40
View user's profile Send private message Visit poster's website ICQ Number 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.