+ defcode "SYSCALL2",8,,SYSCALL2
+ pop %eax // System call number (see <asm/unistd.h>)
+ pop %ebx // First parameter.
+ pop %ecx // Second parameter
+ int $0x80
+ push %eax // Result (negative for -errno)
+ NEXT
+
+ defcode "SYSCALL1",8,,SYSCALL1
+ pop %eax // System call number (see <asm/unistd.h>)
+ pop %ebx // First parameter.
+ int $0x80
+ push %eax // Result (negative for -errno)
+ NEXT
+
+ defcode "SYSCALL0",8,,SYSCALL0
+ pop %eax // System call number (see <asm/unistd.h>)
+ int $0x80
+ push %eax // Result (negative for -errno)
+ NEXT
+
+/*
+ DATA SEGMENT ----------------------------------------------------------------------
+
+ Here we set up the Linux data segment, used for user definitions and variously known as just
+ the 'data segment', 'user memory' or 'user definitions area'. It is an area of memory which
+ grows upwards and stores both newly-defined FORTH words and global variables of various
+ sorts.
+
+ It is completely analogous to the C heap, except there is no generalised 'malloc' and 'free'
+ (but as with everything in FORTH, writing such functions would just be a Simple Matter
+ Of Programming). Instead in normal use the data segment just grows upwards as new FORTH
+ words are defined/appended to it.
+
+ There are various "features" of the GNU toolchain which make setting up the data segment
+ more complicated than it really needs to be. One is the GNU linker which inserts a random
+ "build ID" segment. Another is Address Space Randomization which means we can't tell
+ where the kernel will choose to place the data segment (or the stack for that matter).
+
+ Therefore writing this set_up_data_segment assembler routine is a little more complicated
+ than it really needs to be. We ask the Linux kernel where it thinks the data segment starts
+ using the brk(2) system call, then ask it to reserve some initial space (also using brk(2)).
+
+ You don't need to worry about this code.
+*/
+ .text
+ .set INITIAL_DATA_SEGMENT_SIZE,65536
+set_up_data_segment:
+ xor %ebx,%ebx // Call brk(0)
+ movl $__NR_brk,%eax
+ int $0x80
+ movl %eax,var_HERE // Initialise HERE to point at beginning of data segment.
+ addl $INITIAL_DATA_SEGMENT_SIZE,%eax // Reserve nn bytes of memory for initial data segment.
+ movl %eax,%ebx // Call brk(HERE+INITIAL_DATA_SEGMENT_SIZE)
+ movl $__NR_brk,%eax
+ int $0x80
+ ret
+
+/*
+ We allocate static buffers for the return static and input buffer (used when
+ reading in files and text that the user types in).
+*/
+ .set RETURN_STACK_SIZE,8192
+ .set BUFFER_SIZE,4096
+
+ .bss
+/* FORTH return stack. */
+ .align 4096
+return_stack:
+ .space RETURN_STACK_SIZE
+return_stack_top: // Initial top of return stack.
+
+/* This is used as a temporary input buffer when reading from files or the terminal. */
+ .align 4096
+buffer:
+ .space BUFFER_SIZE
+