Machine Code

Note

Mecrisp-Stellaris 2.4.2-RA used here

For various reasons of speed or efficiency, the Forth programmer may want to insert their own machine code into a Forth program. The following example shows how this is done.

Unlike a C language cross compiler on a PC, where ASM can mostly be inlined as assembly, Forth compiles Forth syntax into machine code, because there is no on MCU Assembler.

This means that to use your own machine code words, Machine Code must be entered directly inbto your Forth Word. This can be done by writing your code in a Assembler such as Gnu AS.

The Sample Assembly Code below, processed by GNU AS, creates a Assembly Listing which is then pasted into your Forth Word.

Sample Assembly code

under construction

Sample Assembly Listing

under construction

Sample Machine Code

under construction

Sample Forth Word

under construction

Note

Mecrisp-Stellaris also has Interactive Assembly Language Words.

Using Machine Code with Mecrisp-Stellaris

Note

Mecrisp-Stellaris 2.4.2-RA used here

Sqrt Example

Sqrt Algorithm from the book “Hacker’s Delight”

: sqrt ( u -- u^1/2 )
  [
  $2040 h, \   movs r0, #0x40
  $0600 h, \   lsls r0, #24
  $2100 h, \   movs r1, #0
  $000A h, \ 1:movs r2, r1
  $4302 h, \   orrs r2, r0
  $0849 h, \   lsrs r1, #1
  $4296 h, \   cmp r6, r2
  $D301 h, \   blo 2f
  $1AB6 h, \   subs r6, r2
  $4301 h, \   orrs r1, r0
  $0880 h, \ 2:lsrs r0, #2
  $D1F6 h, \   bne 1b
  $000E h, \   movs r6, r1
  ]
;
Code Assembly Language Comment
]   Switch to compile state
$2040 h, movs r0, #0x40 Write value of $40 to r0, flags get updated
$0600 h, lsls r0, #24 Shift contents of r0 left 24 with flag update
$2100 h, movs r1, #0 Write value of zero to r1, flags are updated
$000A h, 1:movs r2, r1 Write value of r1 into r2
$4302 h, orrs r2, r0  
$0849 h, lsrs r1, #1  
$4296 h, cmp r6, r2  
$D301 h, blo 2f  
$1AB6 h, subs r6, r2  
$4301 h, orrs r1, r0  
$0880 h, 2:lsrs r0, #2  
$D1F6 h, bne 1b  
$000E h, movs r6, r1  
]   Switch to execute state

Sqrt Dissasembled

see sqrt

20000398: B500  push { lr }
2000039A: 2040  movs r0 #40
2000039C: 0600  lsls r0 r0 #18
2000039E: 2100  movs r1 #0
200003A0: 000A  lsls r2 r1 #0
200003A2: 4302  orrs r2 r0
200003A4: 0849  lsrs r1 r1 #1
200003A6: 4296  cmp r6 r2
200003A8: D301  bcc 200003AE
200003AA: 1AB6  subs r6 r6 r2
200003AC: 4301  orrs r1 r0
200003AE: 0880  lsrs r0 r0 #2
200003B0: D1F6  bne 200003A0
200003B2: 000E  lsls r6 r1 #0
200003B4: BD00  pop { pc }
ok.
Address Code Assembly Language Comment
20000398: B500 push { lr } Push registers onto stack. lr = “Link Register (r14),Stores return information for subroutines, function calls, and exceptions.
2000039A: 2040 movs r0 #40  
2000039C: 0600 lsls r0 r0 #18  
2000039E: 2100 movs r1 #0  
200003A0: 000A lsls r2 r1 #0  
200003A2: 4302 orrs r2 r0  
200003A4: 0849 lsrs r1 r1 #1  
200003A6: 4296 cmp r6 r2  
200003A8: D301 bcc 200003AE  
200003AA: 1AB6 subs r6 r6 r2  
200003AC: 4301 orrs r1 r0  
200003AE: 0880 lsrs r0 r0 #2  
200003B0: D1F6 bne 200003A0  
200003B2: 000E lsls r6 r1 #0  
200003B4: BD00 pop { pc } Pop registers from stack. pc = Program Counter (r15)

Ra Register Allocator Usage

RA Register Alocator Register USAGE
r0 Free scratch register Saved on interrupt entry by hardware
r1 Free scratch register Saved on interrupt entry by hardware
r2 Free scratch register Saved on interrupt entry by hardware
r3 Free scratch register Saved on interrupt entry by hardware
r4 Inner loop count Needs Push and Pop when used otherwise
r5 Inner loop limit Needs Push and Pop when used otherwise
r6 TOS: Top-Of-Stack Stack design is interrupt safe
r7 PSP: Parameter Stack Pointer Stack design is interrupt safE
r8 Unused  
r9 Unused  
r10 Unused  
r11 Unused  
r12 Unused Saved on interrupt entry by hardware
r13 SP Return Stack Pointer  
r14 LR Link Register  
r15 PC Program Counter, always odd