Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

END_PRIOR_IF for short-circuit control-flow in assembler

114 views
Skip to first unread message

Dave Keenan

unread,
May 26, 2014, 4:23:26 AM5/26/14
to
I am familiar with Wil Baden's short-circuit boolean evaluation using ANDIF and ORIF (which I suspect would be better called ORELSE).

: ANDIF S" DUP IF DROP " EVALUATE ; IMMEDIATE
: ORIF S" DUP 0= IF DROP " EVALUATE ; IMMEDIATE

But these don't lend themselves to use in assembly-language where we typically don't evaluate a boolean result to feed to a conditional, instead we directly short-circuit the control-flow based on condition codes like Z, NZ, C, NC etc.

I figured out a way to do this, and it can be used in Forth as well as assembler. It can be done in ANS Forth and makes no assumptions about the implementation of the control-flow stack. I think the hardest part was coming up with a name for
1 CS-ROLL THEN (i.e. CS-SWAP THEN)
If you replace THEN with ENDIF it's not quite so difficult.

: ENDIF POSTPONE THEN ; IMMEDIATE
: END-PRIOR-IF 1 CS-ROLL POSTPONE ENDIF ; IMMEDIATE

The equivalent of the C-like short-circuit OR conditional

IF (p || q || r) doThis ELSE doTheOther ENDIF

is then written with overlapping structures as

p 0= IF
q 0= IF
r IF
END-PRIOR-IF \ endif not q
END-PRIOR-IF \ endif not p
doThis
ELSE \ else r
doTheOther
ENDIF \ endif r

Note the inversion of all but the last condition in the short-circuit OR.

The equivalent of the C-like short-circuit AND conditional

IF (p && q && r) doThis ELSE doTheOther ENDIF

is written as

p IF
q IF
r IF
doThis
ELSE \ else r
END-PRIOR-IF \ endif q
END-PRIOR-IF \ endif p
doTheOther
ENDIF \ endif r

Note that the END-PRIOR-IFs come after the ELSE in the short-circuit AND, whereas they come after the IF in the short-circuit OR.

I don't know how to enforce multiple spaces and hence indentation in this forum, so it's probably lost above, but you can see the intended indentation, and read about the assembly-language application, here:
http://dkeenan.com/AddingStructuredControlFlowToAnyAssembler2.htm

Admittedly Wil Baden's ANDIF and ORIF (or ORELSE) are a lot more readable and don't involve overlapping structures, but I don't see any way of doing the equivalent for assembly language condition codes.

AKK

unread,
May 26, 2014, 7:01:07 AM5/26/14
to
Am 26.05.2014 10:23, schrieb Dave Keenan:
> I am familiar with Wil Baden's short-circuit boolean evaluation using ANDIF and ORIF (which I suspect would be better called ORELSE).
<snip>

Why not just read the flag register to TOS?

Or create your own operations such as
code ADC ( a b -- sum carry-bit ) ... ??

It is Forth after all. ;-)

Paul Rubin

unread,
May 26, 2014, 3:26:31 PM5/26/14
to
Dave Keenan <d.ke...@gmail.com> writes:
> : ANDIF S" DUP IF DROP " EVALUATE ; IMMEDIATE
> : ORIF S" DUP 0= IF DROP " EVALUATE ; IMMEDIATE

I'm having trouble understanding what this is supposed to do. Is it for
a Chuck Moore-sytle IF that doesn't consume the condition arg?

Dave Keenan

unread,
May 26, 2014, 8:22:34 PM5/26/14
to
On Monday, 26 May 2014 21:01:07 UTC+10, AKK wrote:
> Why not just read the flag register to TOS?

One normally only resorts to assembly language for speed, in which case it's OOTQ to waste time moving the flag register to TOS and shifting, ANDing or ORing it. And it seemed somehow inelegant to resort to labels and explicit jumps or gotos.

> Or create your own operations such as
>
> code ADC ( a b -- sum carry-bit ) ... ??

That's fine, but I'm not sure what it has to do with short-circuit conditionals in assembly language, which you might still want to occur in the "??" part.

> It is Forth after all. ;-)

Ah. But it isn't necessarily Forth after all. I had the realisation one day that Forth's elegant control-flow system can be implemented as macros in almost any assembler, not only those that are embedded in Forth systems. This is done by the "brute force" creation of an assembler control-flow stack from eight or so ordinary named assembler variables by writing CS-PUSH and CS-DROP macros that shuffle them up and down, and a CS-SWAP macro. You can read about it here
http://dkeenan.com/AddingStructuredControlFlowToAnyAssembler.htm

The use of this method would make portable assembly-language Forth-sources like eForth.asm even more portable by eliminating explicit jump instructions and replacing them with Forth-like structured control-flow implemented as assembler macros.

Dave Keenan

unread,
May 26, 2014, 9:18:15 PM5/26/14
to
On Tuesday, 27 May 2014 05:26:31 UTC+10, Paul Rubin wrote:
> Dave Keenan writes:
>
> > : ANDIF S" DUP IF DROP " EVALUATE ; IMMEDIATE
> > : ORIF S" DUP 0= IF DROP " EVALUATE ; IMMEDIATE
>
> I'm having trouble understanding what this is supposed to do. Is it for
> a Chuck Moore-sytle IF that doesn't consume the condition arg?

No. Those are Wil Baden's words for doing short-circuit boolean evaluation.
http://rosettacode.org/wiki/Short-circuit_evaluation
http://www.wilbaden.com/neil_bawd/tool2002.txt

Wil wrongly describes them as short-circuit conditionals when they are really short-circuit boolean evaluators. This may seem like a subtle distinction because of course the result of a short-circuit evaluation can be fed to an ordinary conditional, but doing so requires the execution of one more conditional-jump than is required by proper short-circuit conditionals such as those written using END-PRIOR-IF.

If you'll excuse me for renaming ORIF to ORELSE and THEN to ENDIF, with Wil's tools the short-circuit version of

p q OR r OR IF ... ELSE ... THEN

is written as:

p ORELSE \ p DUP 0= IF DROP
q ORELSE \ q DUP 0= IF DROP
r
ENDIF
ENDIF
IF
...
ELSE
...
ENDIF

This will execute a minimum of two conditional jumps, being the first ORELSE and the final IF.

Using END-PRIOR-IF, the same short-circuit-OR conditional is written as:

p 0= IF
q 0= IF
r IF
END-PRIOR-IF \ CS_SWAP ENDIF (q)
END-PRIOR-IF \ CS-SWAP ENDIF (p)
...
ELSE
...
ENDIF

This will execute a minimum of one conditional jump, being the first IF, and does not require any DUPs or DROPs.

So Wil Baden's tools don't give optimal short-circuit conditionals except in the specific case of a short-circuit-AND with no ELSE clause. That's because this can be written as:

p ANDIF
q ANDIF
r IF
...
ENDIF
ENDIF
ENDIF

And yes, I'm aware of Wil's COND ... THENS (i.e. COND ... ENDIFS) to tidy up the multiple ENDIFs, but I'm trying to introduce only one idea at a time here.

Dave Keenan

unread,
Jan 15, 2018, 10:47:25 PM1/15/18
to
I know this thread is 4 years cold, but anyone who comes across this thread should know:

Although on Monday, 26 May 2014 18:23:26 UTC+10, I wrote:
> Admittedly Wil Baden's ANDIF and ORIF (or ORELSE) are a lot more readable and don't involve overlapping structures, but I don't see any way of doing the equivalent for assembly language condition codes.

I have now figured out how to do structured short-circuit AND and OR conditionals in assembler, in a readable manner, without overlapping structures, and with no penalty in speed or compactness. You can read about it here:
http://dkeenan.com/AddingStructuredControlFlowToAnyAssembler2.htm
0 new messages