The above screenshot is the b4ix enhanced interactive shell. The sceen is broken into three sections:
- on top, a view into the systems video buffer, which is pre-initialized with a logo from the bios.
- in the middle, an interactive shell for the
b4aassembly language. - at the bottom, a view of stacks and section of the machine’s ram
# https://rosettacode.org/wiki/Loops/For
:E lb 'e io rt # set up ^E to emit a character
:I cd cd du dc sw dc rt # set up ^I to fetch outer loop counter
:loop du .f du ^I sb c1 ad .f lb '. ^E .n lb '| ^E .n zp rt
5 loop
The ^E syntax calls whatever function the E register is pointing at, and the assembler assigns it when it sees :E.
Here, ^E loads the byte 'e (quoted ascii char) and sends that as a command to the io op, which prints the next character on the stack.
The ^I definition fetches the outer loop counter in a .f … .n (“for/next”) loop.
Since it’s a function call, we have to dig deep into the control stack (cd means copy from control stack to data stack), (du)plicate the counter, and then (sw)ap it with the return address so we can push that back onto the control stack (dc means data -> control), and then rt (return).
Then :loop dupes its argument and uses it as an argument to the .f=/.n= loop.
During these loops, the loop counter is on the control stack, so ^I grabs it as explained earlier, but there is also a copy of the original loop length (5 in this case) on the data stack.
so du ^I sb duplicates the 5, subtracts the outer loop counter, and leaves the result on the stack.
c1 is an op that adds the constant 1 to the stack, and ad adds the top two values, so c1 ad adds 1 to the previous expression to get the length of the inner loop.
.f lb '. ^E .n prints that many dots.
lb '| ^E .n prints the pipe character and ends the outer loop.
then zp rt removes that original 5 that’s been sitting on the stack the whole time (passed in when we explicitly called 5 loop) and returns to the calling function (in this case, the interactive “b4ix” shell.)
b4 is a tiny virtual machine, with a forth-like flavor.
There are currently five implementations:
- ./jlang/, implemented in J.
- ./pas/, implemented in free pascal.
- ./lil/, implemented in lil.
- ./js/, implemented in javascript.
- b4-gd, implemented in GDScript for Godot 4.
The implementations are kept in sync through the tests in ./b4-tests.org
See ./bios/bios.b4a for an example of b4 assembly language.
- b4 github repo
- twitter: @tangentstorm / #b4lang
- reddit: /r/b4lang
B4 is a forth-like virtual machine. Quick intros to forth (free and online):
B4 was strongly influenced by the ngaro virtual machine from retroforth 11, as well as the forth chips from greenarrays.
