/ 2_computers.org
2_computers.org
   1  #+title: Computers
   2  #+author: Michael Raitza
   3  #+subtitle: Barkhausen Institut, Dresden
   4  #+options: ^:nil
   5  #+startup: showall indent
   6  #+property: header-args:uxntal :wrap src text :noweb yes
   7  
   8  * The Computer
   9  
  10  We use the Uxn/Varvara 8-bit virtual computer
  11  
  12  [[https://wiki.xxiivv.com/site/uxn.html][Uxn➚]] :: 8-bit virtual machine
  13  [[https://wiki.xxiivv.com/site/varvara.html][Varvara➚]] :: specification of devices communicating with the Uxn machine
  14  
  15  - simple
  16  - accessible
  17  - supports graphics, sound and interaction
  18  - programmed in [[https://wiki.xxiivv.com/site/uxntal.html][Uxntal➚]]
  19  
  20  * The Uxn/Varvara computer
  21  
  22  #+begin_src text
  23                                           Control Unit              Random access memory
  24         Working Stack (memory)  ¦        +------------+          +- - - +--------+--------+
  25   · ··~-+----+----+----+----+---+        ¦  IF / ID   ¦ <------> | 0000 | i o i o o i i o |
  26         |    |    |    |    |     <----> ¦ Ex / LS  __¦ <--+     +- - - +--------+--------+
  27   · ··~-+----+----+----+----+---+   +--> ¦         |PC¦    |     | 0001 |                 |
  28                                 ¦   |    +---------+--+    |     ·~ ~ ~ · ~ ~ ~ ~ ~ ~ ~ ~ ·
  29          Return Stack (memory)  ¦   |       ↑     |        |     | 00ff |                 |
  30   · ··~-+----+----+----+----+---+   |       |     |        |     +- - - +--------+--------+
  31         |    |    |    |    |     <-+       |     |        |     | 0100 |                 |
  32   · ··~-+----+----+----+----+---+           |     |        |     ·~ ~ ~ · ~ ~ ~ ~ ~ ~ ~ ~ ·
  33                                 ¦           |     |        |     ·      ·                 ·
  34                                             |     ↓        |     ·      ·                 ·
  35                                 +---------------------+    |
  36                                 ¦                     ¦    |        Device memory
  37                                 ¦  + / − / ≤ / ∨ / ∧  ¦    |      +- + -+--------+--------+
  38                                 ¦                     ¦    +----> | 0:0 | o o o o o o o o |
  39                                 +---------------------+           · ~ ~ · ~ ~ ~ ~ ~ ~ ~ ~ ·
  40                                   Arith. Logic Unit               | f:f |                 |
  41                                                                   +- + -+--------+--------+
  42  #+end_src
  43  
  44  * Instruction cycle – Instruction Fetch
  45  
  46  #+begin_src text
  47                                           Control Unit              RAM
  48                          Stack  ¦        +------------+   BYTE   +------+-------
  49                         ----+---+        ¦  IF /      ¦ <------- | 0000 | o o o
  50                          dd | ff  <----> ¦    /     __¦          +------+-------
  51                         ----+---+        ¦         |PC¦ -------> | 0001 |
  52                                 ¦        +---------+--+   ADDR   +~ ~ ~ + ~ ~ ~
  53                                             ↑     |              | 00ff |
  54                                             |     ↓              +------+-------
  55                                 +---------------------+          | 0100 |
  56                                 ¦                     ¦          +~ ~ ~ + ~ ~ ~
  57  #+end_src
  58  
  59  * Instruction cycle – Instruction Decode
  60  
  61  #+begin_src text
  62                                           Control Unit
  63                          Stack  ¦        +-----------------------+
  64                         ----+---+        ¦     / ID           +-----
  65                          dd | ff  <----> ¦    /               |  ¦
  66                         ----+---+        ¦  k r 2      BYTE <-+  ¦
  67                                 ¦        ¦  o o o o o o o o      ¦
  68                                          ¦  ----- ---------      ¦
  69                                          ¦  flags   opcode     __¦
  70                                          ¦                    |PC¦
  71                                          +-----------------------+
  72  #+end_src
  73  
  74  * Instruction cycle – Execute
  75  
  76  #+begin_src text
  77                          Stack  ¦         Control Unit
  78   · ··~-+----+----+----+----+---+   pop  +------------+          +-
  79  Before Ex   | dd | ff | 00 | cd  -----> ¦     /      ¦ <~ ·· ~> |
  80   · ··~-+----+----+----+----+---+        ¦ Ex /     __¦          +-
  81   After Ex   |    | dd | ff | ab  <----- ¦         |PC¦          |
  82   · ··~-+----+----+----+----+---+  push  +---------+--+          ·~
  83                                 ¦        ab ↑     |              |
  84                                             |     ↓ cd, 00       +-
  85                                 +---------------------+          |
  86                                 ¦                     ¦          +~
  87                                 ¦  + / - / ≤ / ∨ / ∧  ¦          ·
  88                                 ¦                     ¦          ·
  89                                 +---------------------+
  90                                   Arith. Logic Unit
  91  #+end_src
  92  
  93  * Instruction cycle – Load/Store
  94  
  95  #+begin_src text
  96                                           Control Unit              RAM
  97                          Stack  ¦        +------------+   BYTE   +------+-------
  98                         ----+---+        ¦     /      ¦ <------- | 0000 | o o o
  99                          dd | ff  <----- ¦    / LS  __¦          +------+-------
 100                         ----+---+        ¦         |PC¦ -------> | 0001 |
 101                                 ¦        +---------+--+   ADDR   +~ ~ ~ + ~ ~ ~
 102                                             ↑     |              | 00ff |
 103                                             |     ↓              +------+-------
 104                                 +---------------------+          | 0100 |
 105                                 ¦                     ¦          +~ ~ ~ + ~ ~ ~
 106  #+end_src
 107  
 108  * First program
 109  #+begin_src uxntal
 110  ;text while ( reference 'text' variable defined below )
 111  BRK
 112  @while ( &str* -- )
 113  	LDAk DUP ?{
 114  		POP POP2 JMP2r }
 115  	#18 DEO
 116  	INC2 !while
 117  
 118  @text "Hello 20 "World! 0a $1
 119  #+end_src
 120  
 121  With cursor inside the source code block:
 122  ~C-c C-c~ :: to run the program and see the output
 123  ~C-c C-v k~ :: to remove (kill) the result again
 124  
 125  *Try this now!*
 126  
 127  Change the program to print a second line of text after =Hello World!=
 128  
 129  * Behavioural analysis
 130  #+begin_src uxntal :eval never
 131  ;text while ( reference 'text' variable defined below )
 132  BRK
 133  @while ( &str* -- )
 134  	LDAk DUP ?{
 135  		POP POP2 JMP2r }
 136  	#18 DEO
 137  	INC2 !while
 138  
 139  @text "Hello 20 "World! 0a $1
 140  #+end_src
 141  
 142  1) program produces the output =Hello␣World!⬎=
 143  
 144  2) output is similar to the line introduced by src_uxntal{@text}
 145  
 146  3) src_uxntal{@text} seems to be a string characters
 147  
 148  4) src_uxntal{@while ( ... -- )} is the program
 149  
 150  5) src_uxntal{@text} is the data
 151  
 152  * Syntax analysis
 153  #+begin_src uxntal :eval never
 154  ;text while ( reference 'text' variable defined below )
 155  BRK
 156  @while ( &str* -- )
 157  	LDAk DUP ?{
 158  		POP POP2 JMP2r }
 159  	#18 DEO
 160  	INC2 !while
 161  
 162  @text "Hello 20 "World! 0a $1
 163  #+end_src
 164  
 165  src_uxntal{( ... )} :: commentary
 166  
 167  src_uxntal{DUP BRK POP while !while} :: program text
 168  
 169  src_uxntal{18 20 0a} :: numbers. To the number *base 16* and not 10!
 170  
 171  src_uxntal{"Hello} character strings (ending at the next space, not the second ="=)
 172  
 173  src_uxntal{@text ;text} are variables?
 174  
 175  * Help yourself!
 176  #+begin_src uxntal :eval never
 177  ;text while ( reference 'text' variable defined below )
 178  BRK
 179  @while ( &str* -- )
 180  	LDAk DUP ?{
 181  		POP POP2 JMP2r }
 182  	#18 DEO
 183  	INC2 !while
 184  
 185  @text "Hello 20 "World! 0a $1
 186  #+end_src
 187  
 188  With cursor inside the source code block:
 189  ~C-c C-h~ ::
 190  - on a word prints a short explanation in the echo area
 191  - on a number prints the decimal value in parenthesis
 192  
 193  *Try this now!*
 194  
 195  ** Uxntal language reference
 196  
 197  Open =Uxntal-reference.org= and fit the window (~M-x fit-window-to-buffer~)
 198  
 199  Full language reference [[elisp:(man "-l uxntal.7")][manpage]] (open with ~C-c C-o~ while cursor on link)
 200  
 201  * Structural analysis
 202  #+begin_src uxntal :eval never
 203  ;text while
 204  BRK
 205  @while ( ### -- )
 206  	#### ### ?{
 207  		### #### ### }
 208  	#18 ###
 209  	#### !while
 210  
 211  @text "xyz 20 "xyz 0a $1
 212  #+end_src
 213  
 214  1) Actions (blue) are grouped by indentation
 215  
 216  2) Actions (blue) and data (green, orange) structured by
 217  
 218     - labelling (=@<word>= notation)
 219  
 220     - curly braces (=?{  ... }= notation)
 221  
 222  3) Program is a series of actions *not* a composition of functions (in mathematical sense) 
 223  
 224  4) Processor executes program instruction by instruction, one blue word after another
 225  
 226  * Semantic analysis – simplify
 227  #+begin_src uxntal
 228  ;text
 229  ( @while '( &str* -- )' )
 230  	LDAk DUP ?{
 231  		POP POP2 BRK }
 232  	#18 DEO
 233  	BRK ( INC2 !while )
 234  
 235  @text "Hello 20 "World! 0a $1
 236  #+end_src
 237  
 238  *Try this now!*
 239  
 240  Run the program
 241  
 242  ** Further Simplification
 243  
 244  #+begin_src uxntal
 245  LIT "H #18 DEO
 246  #+end_src
 247  
 248  *Discussion*
 249  
 250  * Execution by machine
 251  
 252  Memory content (what the machine actually sees)
 253  #+begin_src uxntal :rom dis
 254  LIT "H #18 DEO
 255  #+end_src
 256  
 257  #+RESULTS:
 258  #+begin_src text
 259  |0100   80 48      ( #48 )
 260  |0102   80 18      ( #18 )
 261  |0104   17         ( DEO )
 262  #+end_src
 263  
 264  ** Example execution
 265  #+begin_src text
 266                                           Control Unit              Random access memory
 267                  Working Stack  ¦        +------------+          ·~ ~ ~ · ~ ~ ~ ~ ~ ~ ~ ~ ·
 268   · ··~-+----+----+----+----+---+        ¦  IF / ID   ¦ <------> | 0100 |       80 (LIT)  |
 269         |    |    |    |    |     <----> ¦ Ex / LS ___¦ <--+     +- - - +-----------------+
 270   · ··~-+----+----+----+----+---+   +--> ¦        | PC¦    |     | 0101 |       48 ("H)   |
 271                                 ¦   |    +--------+---+    |     +- - - +-----------------+
 272                   Return Stack  ¦   |       ↑     |        |     | 0102 |       80 (#)    |
 273   · ··~-+----+----+----+----+---+   |       |     |        |     +- - - +-----------------+
 274         |    |    |    |    |     <-+       |     |        |     | 0103 |       18 (18)   |
 275   · ··~-+----+----+----+----+---+           |     |        |     +- - - +-----------------+
 276                                 ¦           |     |        |     | 0104 |       17 (DEO)  |
 277                                             |     ↓        |     ·~ ~ ~ · ~ ~ ~ ~ ~ ~ ~ ~ ·
 278                                 +---------------------+    |
 279                                 ¦                     ¦    |        Device memory
 280                                 ¦  + / − / ≤ / ∨ / ∧  ¦    |      +- + -+-----------------+
 281                                 ¦                     ¦    +----> | 0:0 |                 |
 282                                 +---------------------+           · ~ ~ · ~ ~ ~ ~ ~ ~ ~ ~ ·
 283                                   Arith. Logic Unit               | 1:8 |                 |
 284                                                                   +- + -+-----------------+
 285  #+end_src
 286  
 287  * Understanding Uxntal
 288  
 289  - Representation :: symbolised language → instructions and data are numbers in memory
 290  - Order :: program is the memory image that the UXN computer operates on
 291  
 292  ** Labels
 293  #+begin_src uxntal :rom dis
 294  ;text
 295  @while ( str* -- )
 296      POP POP !while
 297  @text "Hello
 298  #+end_src
 299  
 300  src_uxntal{@text @while ( -- )}, symbolic references to instructions and data
 301    - provide malleable targets, e.g., src_uxntal{;text !while}
 302    - *assign names to numbers*
 303    - help maintaining consistency and intent
 304    - *immaterial* → do not appear in memory
 305  
 306  ** Intrinsics
 307  #+begin_src uxntal :rom dis
 308  ;text
 309  @while ( &str -- )
 310      POP POP !while
 311  @text "Text
 312  #+end_src
 313  
 314  UXN processor instructions
 315    - in capital letters, e.g., src_uxntal{POP INC2 LDA2k}
 316    - *material* → appear exactly where you put them
 317    - fundamental units of compute
 318    - cannot be changed, introspected or taken apart
 319  
 320  Intrinsics have *three modes* appended to their names, e.g., src_uxntal{INC2 STHk JMP2r}
 321    - 2 (short) :: operate on *two bytes*, instead of single bytes
 322    - k (keep) :: *do not consume* elements on stack
 323    - r (return) :: operate on other stack (usually *return stack*)
 324      
 325  ** Runes
 326  #+begin_src uxntal :rom dis
 327  ;text while
 328  BRK
 329  @while ( &str* -- )
 330  	LDAk DUP ?{
 331  		POP POP2 JMP2r }
 332  	#18 DEO
 333  	INC2 !while
 334  
 335  @text "Hello 20 "World! 0a $1
 336  #+end_src
 337  
 338  Language keywords – single-letter (prefix) symbols
 339    - e.g., =@ ; $ # ? { }=
 340    - translate symbols (e.g. labels, strings) into numbers and intrinsics
 341    - can be either *material* or *immaterial*
 342      
 343  * Runes explained
 344  #+begin_src uxntal :rom dis
 345  ;text while
 346  BRK
 347  @while ( str* -- )
 348  	LDAk DUP ?{
 349  		POP POP2 JMP2r }
 350  	#18 DEO
 351  	INC2 !while
 352  
 353  @text "Hello 20 "World! 0a $1
 354  #+end_src
 355  
 356  ~;~ :: Refer to a memory location via a label → /Push named memory location onto stack/ *[ ]*
 357  
 358  ~@~ :: Define a label → /Give a memory location a name/ *[ ]*
 359    
 360  ~?{ }~ :: Conditional jump → /Produce code to execute code under condition/ *[ ]*
 361  
 362  ~#~ :: Literal number → /Produce code to push number onto stack/ *[ ]*
 363  
 364  *Which runes are (im-)material? ('i'/'m')*
 365  
 366  * Runes explained (contd.)
 367  #+begin_src uxntal :rom dis
 368  ;text while
 369  BRK
 370  @while ( str* -- )
 371  	LDAk DUP ?{
 372  		POP POP2 JMP2r }
 373  	#18 DEO
 374  	INC2 !while
 375  
 376  @text "Hello 20 "World! 0a $1
 377  #+end_src
 378  
 379  ~!~ :: Unconditional jump. /Produce code to jump to label/ *[ ]*
 380  
 381  ~"~ :: Raw character string. /Write numeric values of characters into memory/ *[ ]*
 382  
 383  ~$~ :: Relative pad. /Move address of next program fragment by value/ *[ ]*
 384  
 385  * Arithmetic and logic
 386  
 387  Uxntal instructions *do not* take arguments
 388  
 389  They operate on the current bytes on the stack
 390  
 391  ** Example
 392  #+begin_src uxntal :run bin
 393  #12 #13 ADD byte.
 394  #02 #04 MUL byte.
 395  #03 #02 DIV byte. ( Integer division! Fractional part truncated! )
 396  #03 #02 GTH byte.
 397  #00 #01 acc. #02 acc. #03 acc.
 398  
 399  BRK
 400  
 401  @byte. ( b -- )
 402      #18 DEO JMP2r
 403  
 404  @acc. ( a b -- c )
 405      ADD DUP byte. JMP2r
 406  #+end_src
 407  
 408  * Memory operation
 409  
 410  *Data* is either:
 411  - loaded :: copied from memory to stack
 412  - stored :: moved/copied from stack to memory
 413  - consumed :: moved/copied from stack and computed on
 414  - produced :: moved from Arith. Logic Unit onto stack
 415  - stashed :: moved/copied between stacks
 416  
 417  ** Loading data
 418  #+begin_src uxntal :rom dis
 419  #12
 420  LIT 13
 421  LIT2 1415
 422  #1617
 423  .data
 424  ,data
 425  ;data
 426  
 427  @data 05 "Hello
 428  #+end_src
 429  
 430  ** Consume / produce data
 431  #+begin_src uxntal :run bin
 432  #02 #03 ADD #01 SUB byte.
 433  #03 #04 ADDk SUB SUB byte.
 434  BRK
 435  @byte. ( b -- )
 436      #18 DEO JMP2r
 437  #+end_src
 438  
 439  ** Storing data
 440  #+begin_src uxntal :rom dis
 441  #12 #05 STZ
 442  #13 #06 STR
 443  #14 ;data STA
 444  
 445  @data 05 "Hello
 446  #+end_src
 447  
 448  * Stack operation (advanced)
 449  
 450  ** Algorithm
 451  1) Get number =n= of elements on working stack
 452  2) If =n > 0= then goto 3) else Stop
 453  3) print top element on working stack
 454  4) Goto 1)
 455  
 456  ** Program
 457  #+begin_src uxntal :run bin
 458  |04 @System/wst
 459  
 460  |100
 461  @on-reset ( -> )
 462      #01 #02 #03 #04 #05
 463      wst.
 464      #05
 465      wst.
 466      BRK
 467  
 468  @wst. ( ... -- ... )
 469      LITr -System/wst DEIr ( { orig-wst } )
 470      &loop [
 471          LITr -System/wst  ( { dev orig-wst } )
 472          DEIr              ( { wst orig-wst } )
 473          LITr 01 LTHr      ( { done? orig-wst } )
 474          LITr _/done JCNr
 475          STH               ( { a done? orig-wst } )
 476          LITr 18 DEOr
 477      ] !/loop
 478      &done
 479      LITr -System/wst DEOr
 480      JMP2r
 481  #+end_src
 482  
 483  * Words
 484  
 485  Intrinsics and labels which are used as instructions are called *words*
 486  #+begin_src uxntal :eval never
 487  ADD LIT           ( intrinsics are words )
 488  @foo ( -- ) JMP2r ( blue labels are words )
 489  @data 1234 "text  (  red labels are data )
 490  #+end_src
 491  
 492  No *substantial* difference between data and instructions!
 493  
 494  Colours (red, blue, orange, green) show the *intended* meaning!
 495  
 496  *Actual* meaning is determined by the position in memory.
 497  
 498  Words provide *intention* and make instruction patterns reusable
 499  
 500  * Defining new words
 501  
 502  To define a word =foo=, write
 503  #+begin_src uxntal :eval never
 504  @foo ( a* b c -- d )
 505  	POP POP POP2
 506      JMP2r
 507  #+end_src
 508  
 509  Consumes *three* elements on stack
 510  - =c= :: a byte
 511  - =b= :: also a byte
 512  - =a*= :: a short (two bytes, signified by =*=)
 513  
 514  Puts *one* elements on stack
 515  - =d= :: a byte
 516  
 517  Word definition promises that:
 518  - it consumes (pops) *four bytes* off stack (neither more, nor less!)
 519  - it pushes back *one byte* onto stack
 520  - both effects may not be offset against each other!
 521  
 522  * Calling words
 523  
 524  *Calling a word* means executing instructions from a *different location*
 525  
 526  ** Linear execution
 527  #+begin_src uxntal :rom dis :wrap src uxntal
 528  #10 DUP INC SWP SUB POP
 529  #+end_src
 530  
 531  #+RESULTS:
 532  #+begin_src uxntal
 533  |0100   80 10      ( #10 )
 534  |0102   06         ( DUP )
 535  |0103   01         ( INC )
 536  |0104   04         ( SWP )
 537  |0105   19         ( SUB )
 538  |0106   02         ( POP )
 539  #+end_src
 540  
 541  Executes always the *next* instruction, =100=, =102=, =103=, ...
 542  
 543  ** Calling a word
 544  #+begin_src uxntal :rom dis :wrap src uxntal
 545  |100 #00 #20 #02 mac #10 #04 mac
 546  @mac ( c a b -- c' ) MUL ADD JMP2r
 547  #+end_src
 548  
 549  #+RESULTS:
 550  #+begin_src uxntal
 551  |0100   80 00      ( #00 )
 552  |0102   80 20      ( #20 )
 553  |0104   80 02      ( #02 )
 554  |0106   60 00 07   ( mac )
 555  |0109   80 10      ( #10 )
 556  |010b   80 04      ( #04 )
 557  |010d   60 00 00   ( mac )
 558  
 559  @mac
 560  |0110   1a         ( MUL )
 561  |0111   18         ( ADD )
 562  |0112   6c         ( JMP2r )
 563  #+end_src
 564  
 565  *** Observations
 566  At call of src_uxntal{|0106 mac}
 567  - execution continues at memory location src_uxntal{|0110}
 568  - src_uxntal{JMP2r} *returns* to memory location src_uxntal{|0109}
 569  - execution continues at that memory location
 570  
 571  Executes =100=, =102=, =104=, =106= → =110=, =111=, =112= → =109=
 572  
 573  * Different types of word calls
 574  :PROPERTIES:
 575  :CUSTOM_ID: while-loops
 576  :END:
 577  
 578  Not all calls are supposed to return
 579  #+begin_src uxntal
 580  ;text while ( reference 'text' variable defined below )
 581  BRK
 582  @while ( &str* -- )
 583  	LDAk DUP ?{
 584  		POP POP2 JMP2r }
 585  	#18 DEO
 586  	INC2 !while
 587  
 588  @text "Hello 20 "World! 0a $1
 589  #+end_src
 590  
 591  src_uxntal{!while} jumps without return:
 592  - unconditional jump (i.e., *always jump*)
 593  - this makes a loop
 594  
 595  src_uxntal{?...} jumps also without return
 596  - conditional jump (i.e., *jump if ...*)
 597  - loop is terminated inside the construct with src_uxntal{BRK}
 598  
 599  ** Loops
 600  #+begin_src text
 601       +----------------------+
 602       | lb     LDAk (@while) |<---+
 603       | lb     DUP           |    |
 604       | lh     JCI  (?{)     |--+ |
 605       | lh     ...           |  | |
 606    +--| lh     BRK           |  | |
 607    |  | lb     #18  (} )     |<-+ |
 608    |  | lb     ...           |    |
 609    |  | lb     JMI  (!while) |----+
 610    |  +----------------------+
 611    | 
 612    +-> ...
 613  #+end_src
 614  
 615  * Stack effect notation (advanced)
 616  
 617  Comment src_uxntal{ @f ( ... -- ... ) } is the *stack effect notation*
 618  
 619  1. Purely informational for assembler
 620  2. Used for sanity checking word definitions
 621  3. Multiple forms:
 622     - src_uxntal{ @f ( ... -- ... ) } :: untyped stack effect
 623       - not sanity checked
 624       - word returns to call site
 625     - src_uxntal{ @f ( ... -: ... ) } :: typed stack effect
 626       - sanity checked, bytes counted
 627       - word returns to call site
 628     - src_uxntal{ @f ( ... -> ... ) } :: vector
 629       - sanity checked, bytes *not* counted
 630       - word *does not* return
 631  
 632  4. Stack value notations:
 633     - src_uxntal{ ( a, a^ ) } :: single-byte value
 634     - src_uxntal{ ( b* ) } :: short (two-byte) value
 635     - src_uxntal{ ( -- ) } :: *no* values consumed/produced
 636     - src_uxntal{ ( ... -- ... ) } :: *unknown* number of values
 637  
 638  * Development tools
 639  
 640  Select what is done with a Uxntal source block via header arguments
 641  #+begin_src org :results replace
 642  ,#+begin_src uxntal
 643  ,|100
 644  @on-reset ( -> )
 645  	POPk #10 #18 DEO BRK
 646  ,#+end_src
 647  #+end_src
 648  
 649  Common header arguments:
 650  | Header argument | Value            | Action                                            |
 651  |-----------------+------------------+---------------------------------------------------|
 652  | :rom            | t                | Print ROM contents instead of running program     |
 653  |                 | dis              | Print disassembled ROM contents                   |
 654  | :run            | debug            | Run program in graphical debugger                 |
 655  |                 |                  | (limited text output, no input)                   |
 656  |                 | bin              | Print output as hexadecimal (to see non-printable |
 657  |                 |                  | characters or numeric results)                    |
 658  |                 | interactive      | Run program in interactive shell                  |
 659  |                 | graphical        | Run as graphical program                          |
 660  | :results        | none             | Do not print any output                           |
 661  | :wrap           | "src uxntal ..." | Print output as Uxntal source block               |
 662  
 663  * Graphical step debugger beetbug
 664  #+attr_html: :width 1000px :align center
 665  [[file:img/2_beetbug.png]]
 666  
 667  ~F1~ :: scale graphical display by 2x, then 3x ([[https://wiki.xxiivv.com/site/beetbug.html][full doc➚]])
 668  #+begin_src text
 669                   +-------------------------------------------------------+
 670                   | 0100                  Work   Return  ⏮      ▶    →    |
 671                   | program ctr. (PC)     Stack  Stack   reset  run  step |
 672                   |                                                       | 
 673                   | disassembled code                    memory content   |
 674                   +-------------------------------------------------------+
 675  #+end_src
 676  
 677  * Debugging a program
 678  
 679  Run the code below
 680  
 681  *Try this now!*
 682  
 683  #+begin_src uxntal :run debug :results none
 684  ;text while ( reference 'text' variable defined below )
 685  BRK
 686  @while ( &str* -- )
 687  	LDAk DUP ?{
 688  		POP POP2 JMP2r }
 689  	#18 DEO
 690  	INC2 !while
 691  
 692  @text "Hello 20 "World! 0a $1
 693  #+end_src
 694  
 695  * Controlling debug – breakpoints
 696  
 697  [[https://wiki.xxiivv.com/site/varvara.html#system][System device➚]] =System/debug= halts execution at point of its access, called *breakpoint*
 698  
 699  *Try this now* 
 700  #+begin_src uxntal :run debug :results none
 701  ;text while ( reference 'text' variable defined below )
 702  BRK
 703  @while ( &str* -- )
 704  	LDAk DUP ?{
 705  		POP POP2 JMP2r }
 706  	#18 DEO
 707      debug ( <- breakpoint )
 708  	INC2 !while
 709  
 710  @debug ( -- ) [ LIT2 01 -System/debug ] DEO JMP2r
 711  
 712  @text "Hello 20 "World! 0a $1
 713  
 714  |0e @System/debug
 715  #+end_src
 716  
 717  * Excursion: Labels and scope
 718  
 719  - src_uxntal{@... } :: Top-level or *scope* label
 720  - src_uxntal{$...} :: Sub-scope label
 721  
 722  *Example* 
 723  #+begin_src uxntal :eval never
 724  @strlen ( str* -- n* )
 725      LIT2r 0000
 726  	&l ( -- )
 727  		LDAk ?{ POP2 STH2r JMP2r }
 728  		INC2r INC2 !&l
 729  #+end_src
 730  
 731  src_uxntal{&l} ≡ src_uxntal{@strlen/l}
 732  Benefit:
 733  - meaning of =l= limited to scope =strlen= → =l= reusable in different scope
 734  - can be called with src_uxntal{!&l} → renaming =strlen= does not break call to =l=
 735  
 736  * Labels – effective use
 737  
 738  ** Constants
 739  Define a complex structured constant like the [[https://wiki.xxiivv.com/site/varvara.html#console][Console device➚]] ports
 740  #+begin_src uxntal :eval never
 741  |10 @Console/vector $2 &read $1 &unused $4 &type $1 &write $1 &error $1
 742  
 743  |100 @on-reset ( -> ) ;on-console .Console/vector DEO BRK
 744  @on-console ( -> ) .Console/read DEI POP BRK ( read one char )
 745  #+end_src
 746  
 747  ** Scoped words & data
 748  
 749  Define a fixed buffer with a capacity pointer =cap=
 750  #+begin_src uxntal :run interactive :results none
 751  <<lib.org:defs()>>
 752  |00 @Console/buf [ $1f &cap $1 ]
 753  
 754  |100 @on-reset ( -> ) ;Console/on-console .Console/vector DEO2 BRK
 755  
 756  @Console/on-console ( -> )
 757  	.&read DEI
 758  	DUP #0a NEQ ?{ ;&buf str. #800f DEO BRK } ( print &buf and halt )
 759  	[ LIT2 -&cap &ptr -&buf ] ( keep location of last char in &buf here )
 760  	( clamp ) NEQk ?{ POP POP2 BRK } ( do not overrun &cap (size of &buf)! )
 761  	INCk ,&ptr STR
 762  	NIP STZ BRK
 763  
 764  <<lib.org:lib()>>
 765  #+end_src
 766  
 767  * Text output
 768  
 769  Run the code below
 770  
 771  With cursor inside source code block:
 772  ~C-c C-v C-v~ :: Show full source block in separate window
 773  
 774  With cursor inside full source window:
 775  ~C-x C-s~ :: Save expanded code back into original file
 776  
 777  *Try this now!*
 778  
 779  1. Play with the code and find out how it works
 780  
 781  2. Change the code to print the length of the original string as well.
 782  
 783  3. Refactor (rewrite) the code to re-use =Length:␣= prefix string instead of copying it
 784  
 785  *Hint:* Indentation and square brackets =[]= purely cosmetic to clarify *intention* of the code
 786  
 787  Time: *15 minutes* 
 788  #+begin_src uxntal
 789  (
 790  @|Common constants )
 791  <<lib.org:defs()>>
 792  
 793  |100
 794  @on-reset ( -> )
 795  	{ "---- -+ "Text -+ "output -+ "---- -^NL $1 } strr.
 796      ;&txt-label str.
 797      ;&txt str.
 798      ;&cpy-label str.
 799      ;&cpy str.
 800  
 801      ;&cpy ;&txt copy-str
 802      DUP2 [
 803          ;&txt-label str. str.
 804          strlen ]
 805      DUP2 [
 806          { "Length: -+ $1 } strr. dec. NL.
 807          LIT2 "0x short. hex. NL. ]
 808      BRK
 809  
 810      &txt-label "orig: -+ $1
 811      &cpy-label "copy: -+ $1
 812      &txt "This -+ "is -+ "the -+ "original -^NL $1
 813      &cpy "This -+ "is -+ "the -+ "copy -^NL $1
 814  
 815  (
 816  @|Library code )
 817  <<lib.org:lib()>>
 818  #+end_src
 819  
 820  * Excursion: numbers and computation
 821  
 822  Common number system: Ten digits. 0 to 9
 823  
 824  
 825  Simplest decision: Yes / No
 826  
 827  Simplest result: True / False
 828  
 829  
 830  Simplest number system: Two digits. Say, 0 and 1
 831  
 832  * Control structures
 833  
 834  Control structures make programs compact and versatile
 835  
 836  They must:
 837  1) break the linear program flow and *jump* to a remote location
 838  2) read data as a *condition* whether to jump or continue
 839  
 840  Uxntal control instructions:
 841  - src_uxntal{?} :: continues execution at the location *next in memory*
 842  
 843    Used almost exclusively. New program location known ahead of time.
 844    
 845  - src_uxntal{JCN} :: continues execution at the location *on top of stack*
 846  
 847    Rarely used. New program location depends on other factors unknown ahead of time.
 848  
 849  ** Decisions
 850  
 851  *Try this now!*
 852  
 853  Run the example. Observe the difference in the implementation of =more-than= and =more-than'=.
 854  
 855  *Discussion*
 856  
 857  #+begin_src uxntal
 858  <<lib.org:defs()>>
 859  |100 #16 #15 [ LIT2r =more-than ] { !more-than' } 2bi BRK
 860  
 861  @more-than ( x y -- )
 862  	GTH ?yes
 863      !no
 864  
 865  @more-than' ( x y -- )
 866  	GTH ?{ { "No -^NL $1 } strr. JMP2r }
 867      { "Yes -^NL $1 } strr. JMP2r
 868  
 869  @yes ( -- ) { "Yes -^NL $1 } strr. JMP2r
 870  @no ( -- ) { "No -^NL $1 } strr. JMP2r
 871  <<lib.org:lib()>>
 872  #+end_src
 873  
 874  ** Loops 2
 875  :PROPERTIES:
 876  :CUSTOM_ID: for-loops
 877  :END:
 878  
 879  Up- and down-counting loops.
 880  
 881  See [[file:lib.org::#dotimes-combinators][dotimes-up, dotimes-down combinators]] for general solution
 882  #+begin_src uxntal
 883  <<lib.org:defs()>>
 884  
 885  |100 #0a dotimes-down' BRK
 886  @dotimes-down' ( cnt [q*] -- )
 887      &l ( cnt -- cnt' )
 888          DUP #00 EQU ?{
 889              DUP bdec. { ". -+ "time -^NL $1 } strr.
 890              #01 SUB !&l }
 891      POP JMP2r
 892  <<lib.org:lib()>>
 893  #+end_src
 894  
 895  #+begin_src uxntal
 896  <<lib.org:defs()>>
 897  
 898  |100 #0a dotimes-up' BRK
 899  @dotimes-up' ( lim -- )
 900  	#00 ( ctr )
 901      &l ( lim ctr -- lim ctr' )
 902          DUP2 EQU ?{
 903          	INC
 904              DUP bdec. { ". -+ "time -^NL $1 } strr.
 905              !&l }
 906      POP JMP2r
 907  <<lib.org:lib()>>
 908  #+end_src
 909  
 910  * Construction of numbers
 911  
 912  ** Numbers as multiples of a unit length
 913  #+begin_src txt
 914   +                    length 0
 915   +-+                  length 1
 916   +-+-+                length 2
 917   +-+-+-+-+            length 4
 918   +-+-+-+-+-+-+-+-+    length 8
 919  
 920   0                   1                   2
 921   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+   length 20
 922   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
 923  #+end_src
 924  
 925  ** Numbers as strings of digits in order of magnitude
 926  
 927  *Big endian*
 928  =142 = ... + 0 × 10ⁿ + ... + 0 × 10³ + 1 × 10² + 4 × 10¹ + 2 × 10⁰=
 929  
 930  *Little endian*
 931  =142 = 2 + 10 × (4 + 10 × (1 + 10 × (0 + 10 × ( ... ))))=
 932  
 933  * Alternative number bases
 934  
 935  ** Base 2 – binary
 936  #+begin_src text
 937  0                                                               1
 938  +- - - - - - - - - - - - - - - -+- - - - - - - - - - - - - - - -+
 939  0                               1                               0
 940  +- - - - - - - -+- - - - - - - -+- - - - - - - -+- - - - - - - -+
 941  0               1               0               1               0
 942  +- - - -+- - - -+- - - -+- - - -+- - - -+- - - -+- - - -+- - - -+
 943  0       1       0       1       0       1       0       1       0
 944  +- -+- -+- -+- -+- -+- -+- -+- -+- -+- -+- -+- -+- -+- -+- -+- -+
 945  0   1   0   1   0   1   0   1   0   1   0   1   0   1   0   1   0
 946  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 947  0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
 948  #+end_src
 949  
 950  ** Base 16 – hexadecimal
 951  #+begin_src text
 952  0                               1                               2
 953  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 954  0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f 0
 955  #+end_src
 956  
 957  * Finite number space
 958  
 959  ** 5 bit (binary digit) number space
 960  #+begin_src text
 961  0                               1                               0
 962  +- - - - - - - - - - - - - - - -+- - - - - - - - - - - - - - - -+
 963  0               1               0               1               0
 964  +- - - - - - - -+- - - - - - - -+- - - - - - - -+- - - - - - - -+
 965  0       1       0       1       0       1       0       1       0
 966  +- - - -+- - - -+- - - -+- - - -+- - - -+- - - -+- - - -+- - - -+
 967  0   1   0   1   0   1   0   1   0   1   0   1   0   1   0   1   0
 968  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 969  0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
 970                                                                  ↑ rolling over
 971  #+end_src
 972  
 973  *How many different numbers?*
 974  
 975  ** Collections of bits
 976  
 977  - Byte :: string of *8 bits*
 978    - Depending on context, ranges from 5–9 bits length
 979    - Basic unit of memory:
 980      - 1 stack position ≔ 1 byte
 981      - 1 memory address / byte
 982    - *Notation* =1 B=, =128 B=
 983  
 984  - Nibble :: string of *4 bits*, i.e., one hexadecimal digit
 985  
 986  - Short :: string of *2 bytes*, i.e., 16 bits
 987  
 988             | Notation          | Nibble | Byte       | Short                  |
 989             |-------------------+--------+------------+------------------------|
 990             | Binary (·₂)       | 0101   | 1001'0110  | 0111'1011'0000'1000    |
 991             |                   |        |            |                        |
 992             | Hexadecimal (·₁₆) | 4, a   | 00, 0a, 5c | fffe, 0001, abcd, ad8e |
 993  
 994  ** Important relations
 995  
 996  - 1 byte :: 2 nibbles → high nibble, low nibble
 997  
 998    e.g. =1001'0110₂= ≡ =96₁₆= → =1001₂=, =9₁₆= (high n.), =0110₂=, =6₁₆= (low n.)
 999  
1000  
1001  - 1 short :: 2 bytes → high byte, low byte
1002  
1003    e.g. =f784₁₆= → =f7₁₆= (high B.), =84₁₆= (low B.)
1004  
1005  * Numeric operations
1006  
1007  ** Addition / Subtraction
1008  
1009  Operations "roll over" at the end of the number space.
1010  Apart from roll over, the operations are complete.
1011  #+begin_src uxntal :run bin
1012  #ff #01 ADD byte.
1013  #00ff #0001 ADD2 short.
1014  #fe #05 ADD byte.
1015  #02 #04 SUB byte.
1016  
1017  BRK
1018  @short. ( s* -- ) SWP byte'. !byte'.
1019  @byte. ( b -- ) #cc byte'. ( >> )
1020  @byte'. ( b -- ) #18 DEO JMP2r
1021  #+end_src
1022  
1023  ** Multiplication
1024  
1025  Multiplication rolls over as well
1026  #+begin_src uxntal :run bin
1027  #40 DUP MUL byte.
1028  #7f DUP MUL byte.
1029  
1030  BRK
1031  @byte. ( b -- ) #cc byte'. ( >> )
1032  @byte'. ( b -- ) #18 DEO JMP2r
1033  #+end_src
1034  
1035  ** Division
1036  
1037  Division is *not* mathematically complete and only keeps the integral part
1038  #+begin_src uxntal :run bin
1039  #05 #02 DIV byte.
1040  
1041  BRK
1042  @byte. ( b -- ) #cc byte'. ( >> )
1043  @byte'. ( b -- ) #18 DEO JMP2r
1044  #+end_src
1045  
1046  * Text input
1047  
1048  Run the code below
1049  
1050  *Try this now!*
1051  
1052  1. Change the program such that it ends after 3 inputs
1053  2. Study the [[https://wiki.xxiivv.com/site/varvara.html#console][Console device➚]] to learn about =Console/...=
1054  3. Change the program again such that the first user input is the
1055     number of inputs after which the program should end
1056  
1057  Time: *30 minutes*
1058  #+begin_src uxntal :run interactive :results none
1059  ( Common constants )
1060  <<lib.org:defs()>>
1061  
1062  |000
1063  @t/buf $2f &cap $1
1064  
1065  |100
1066  @on-reset ( -> )
1067  	{ "---- -+ "Text -+ "input -+ "---- -^NL $1 } strr.
1068      ;t/on-console .Console/vector DEO2
1069      t/prompt
1070      BRK
1071  
1072  @t/prompt ( -- )
1073  	{ "Your -+ "input -+ "(end -+ "with -+ "return): -+ $1 } strr.
1074      JMP2r
1075  
1076  @t/on-console ( -> )
1077  	[ LIT2 02 -Console/type ] DEI LTH ?{ .Console/read DEI !/on-push }
1078      BRK
1079  
1080  @t/on-push ( c -> )
1081  	DUP .^CR EQU ?/on-done ( handle carriage-return control character )
1082  	DUP .^NL EQU ?/on-done ( handle new-line control character )
1083  	DUP #1f GTH ?{ POP BRK } ( drop any other non-printable character )
1084  	[ LIT2 -&cap &ptr -&buf ] ( keep location of last char in &buf here )
1085  	( clamp ) NEQk ?{ POP POP2 BRK } ( do not overrun &cap (size of &buf)! )
1086  	INCk ,&ptr STR
1087  	NIP STZ
1088  	BRK
1089  
1090  @t/on-done ( c -> )
1091  	POP [ LIT2 -&buf _&ptr ] LDR
1092      ( empty input? ) EQUk ?terminate
1093      { "Got: -+ $1 } strr.
1094      ( 0-term. string ) #00 ,&ptr LDR INCk ,&ptr STR STZ
1095      ;&buf str. NL.
1096      ( reset input ptr ) .&buf ,&ptr STR
1097      t/prompt
1098      BRK
1099  
1100  @terminate ( -> )
1101  	#80 .System/state DEO BRK
1102  
1103  ( Library code )
1104  <<lib.org:lib()>>
1105  #+end_src
1106  
1107  * Excursion – The Art of Computer Programming
1108  
1109  Generally, you need a high frustration tolerance
1110  
1111  Your patient (the computer program)
1112  - does neither heal on its own,
1113  - nor does it die when you ignore it
1114  
1115  It stays infuriatingly the same (misbehaving program) until *you* fix it
1116  
1117  Additionally:
1118  Wrong programs behave *chaotically*! (As opposed to people which behave /irrationally/)
1119  
1120  → one single wrong byte can make a program do something entirely different!
1121  
1122  read: [[doi:10.1145/3726485]["Analyzing Krazy Kode"]]
1123  
1124  ** "Rules of engagement"
1125  
1126  1) Note down the expected actions of a program in your own words.
1127     Start with a coarse description
1128     
1129  2) Pick a part of the problem that you think, you have understood
1130     (not necessarily the first item).
1131     Implement it as a simple program with synthetic input
1132     
1133  3) Make use of documentation and helpful tools (e.g., ~C-c C-h~).
1134     Split the Emacs frame (~C-x 3~, ~C-x 1~) to show docs and code side by side
1135  
1136  4) Pick names for words and structure your code that shows your *intention*
1137      
1138  5) When unsure /why/ a word does not work, make a copy and work on it in a smaller
1139     program (see point 2). *Copies are cheap.*
1140     
1141  6) Do not throw away old code early. It contains thoughts that may turn out valid after all
1142     
1143  7) When you understand your misconception, refine your notes from 1)
1144  
1145  8) Once your code works, tidy it up, document it
1146  
1147  9) Grow your program from your working nucleus. If necessary, rework your code in
1148     isolation until it fits the larger program
1149     
1150  * Exercise – Writing a game
1151  
1152  1) Write the following game; you may use the code below as a starting point!
1153  
1154     Use your knowledge from previous examples on how to structure code, store data and make
1155     decisions.
1156  
1157     The rules of the game are:
1158     1) Each turn you roll a die. The points you rolled are added to your total.
1159     2) You may stop at any time and keep the total as your win.
1160     3) If you keep rolling and roll a =1=, you lose all your points and the program ends.
1161  
1162     The rolled die and the total is printed after each roll.
1163  
1164  2) Instead of ending the program, ask whether the player wants to play another round.
1165     Additionally, print the high score of all rounds at the end of each game.
1166  
1167  3) (/Advanced/) Read up on the [[https://wiki.xxiivv.com/site/varvara.html#file][File device]] and implement a permanent high score file!
1168     Print an additional message after each game presenting the current high score and
1169     whether the player has beaten it.  Next, implement a high score table with 4
1170     entries and ask for the players name.
1171  
1172  Some guidance to help with your task:
1173  
1174  1. Read through the rules and write down the steps that the program has to take.  E.g.:
1175     1) ask player whether to continue or end the game
1176     2) read user input and decide: yes (→3) no (→n)
1177     3) roll die
1178     4) ...
1179     n) end program with a win
1180     
1181     Remember to come back to this list whenever you find an error or when you need to add
1182     more steps!
1183  
1184  2. Run src_uxntal{rnd'} in isolation to see what it does.  Implement src_uxntal{roll} that
1185     always produces a number between 1 and 6.
1186  
1187  #+begin_src uxntal :run interactive
1188  <<lib.org:defs()>>
1189  
1190  |100 @on-reset ( -> )
1191  	( setup ... )
1192      BRK
1193  
1194  @rnd' ( -- r )
1195  	[ LIT2 &r f793 ]
1196  	( 5*R+35 ) #0005 MUL2 #0023 ADD2
1197  	( R-R/6547*6547 ) DUP2 #1993 DIV2 #1993 MUL2 SUB2
1198  	.Datetime/minute DEI2 ADD2 { ,&r STR2 JMP2r } keep2 ADD
1199  	JMP2r
1200  
1201  @input ( -> )
1202  	( handle user input )
1203  	BRK
1204  
1205  ( ... game logic ... )
1206  
1207  <<lib.org:lib()>>
1208  #+end_src