Expressions

Brass has a fairly stupid expression parser, and as to maintain backwards compatibility with TASM's even more stupid expression parser it is strongly recommended to leave no trace of ambiguity in your expressions and to wrap (parentheses) around everything. In example, TASM would calculate 1+2*3+4*5 as ((((1+2)*3)+4)*5), giving you 65. Brass, however, would calculate it as 27. Be very careful, and to make sure your expression is evaluated correctly type it in as 1+(2*3)+(4*5).

Brass offers the following operators:

OperatorActionExample
+Addition4+59
-Subtraction3-21
*Multiplication5*210
/Division16/28
%Modulo3%21
&Bitwise AND%1010&%1100%1000
|Bitwise OR%0011|%1001%1011
^Bitwise XOR%1101^%0110%1011
!Boolean NOT!01
~Bitwise NOT (One's complement)~%1011%0100
&&Boolean AND1&&11
||Boolean OR0||11
<<Bitwise shift left%0011<<1%0110
>>Bitwise shift right%0100>>2%0001
¬Two's complement (negate)5+¬14
==Equality54==(50+4)1
!=Inequality12!=(6*2)0
<Less than4<30
>Greater than35>121
<=Less than or equal to32<=(30+2)1
>=Greater than or equal to'p'>='q'0
?:Ternary0?(32+4):55
$Instruction pointer$$9D93
#Current page#0

Any boolean operators treat zero as false and any nonzero to be true.

The ternary operator is a very useful one and can be used as an inline conditional. It takes this form:

(boolean expression)?(returned if true):(returned if false)

If the expression returns true (nonzero) then the the value just after the ? is returned - if the expression returns false (zero) then the value after the : is returned.

Prefixing a label name with a : colon returns the label's page number rather than address. For example:

.page 0

    ld hl,function  ; hl = $F001
    ld a,:function  ; a = 4
    ld b,#          ; b = 0 (current page number)
    
.page 4
.org $F001
function:
    push ix
    call _do_something
    pop ix
    ret

Note that Brass uses double-precision values in a lot of the expressions (it will naturally use integer values for integer operations, chiefly the bitwise operations). You must use the decimal point "." regardless of how your machine is set up (the comma, for example, is used between arguments).

You can "cast" values, however; for example:

.echoln -1634.3        ; -1634.3
.echoln word(-1634.3)  ; -1634
.echoln uword(-1634.3) ; 63902
.echoln byte(-1634.3)  ; -98

As you can see from the last two, the value is adjusted or trucated (quite drastically in the case of the byte). Note that Brass doesn't really understand the concept of types - everything is stored as a double. This can get rather confusing if you start using the fixed point 'type', for example:

.echoln fp8.8(2.00) ; 512
.echoln fp8.8(0.25) ; 64
.echoln fp4.4(1.40) ; 22

See the .var directive for more information on the different data types.