SkillAgentSearch skills...

B4

b4 : a tiny forth-like virtual machine

Install / Use

/learn @tangentstorm/B4
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

#+title: The b4 virtual machine

  • Demo

[[file:ref/b4ix-rosetta.png]]

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 =b4a= assembly language.
  • at the bottom, a view of stacks and section of the machine's ram

** explanation of the demo code

#+begin_src b4a

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 #+end_src

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.)

  • About b4

b4 is a tiny virtual machine, with a forth-like flavor.

There are currently five implementations:

  • [[./jlang/]], implemented in [[https://code.jsoftware.com/wiki/Main_Page][J]].
  • [[./pas/]], implemented in [[https://www.freepascal.org/][free pascal]].
  • [[./lil/]], implemented in [[https://beyondloom.com/decker/lil.html][lil]].
  • [[./js/]], implemented in javascript.
  • [[https://github.com/tangentstorm/b4-gd][b4-gd]], implemented in GDScript for [[https://docs.godotengine.org/en/stable/][Godot 4]].

The implementations are kept in sync through the tests in [[./b4-tests.org]]

See [[file:./b4a/bios.b4a][bios.b4a]] for an example of b4 assembly language.

  • Links
  • [[https://github.com/tangentstorm/b4][b4 github repo]]
  • twitter: [[https://twitter.com/tangentstorm][@tangentstorm]] / [[https://twitter.com/#!/search/realtime/%23b4lang][#b4lang]]
  • reddit: [[http://reddit.com/r/b4lang][/r/b4lang]]
  • Background

B4 is a forth-like virtual machine. Quick intros to forth (free and online):

  • [[http://www.colorforth.com/POL.htm][Programming a Problem-Oriented Language]]
  • [[http://www.forth.com/starting-forth/][Starting Forth]]

B4 was strongly influenced by the [[http://retroforth.org/docs/The_Ngaro_Virtual_Machine.html][ngaro virtual machine]] from retroforth 11, as well as the [[https://www.greenarraychips.com/home/documents/index.php#architecture][forth chips from greenarrays]].

View on GitHub
GitHub Stars40
CategoryDevelopment
Updated18d ago
Forks4

Languages

TypeScript

Security Score

75/100

Audited on Mar 23, 2026

No findings