# Assembling binaries Collapse OS features many assemblers. Each of them have their specificities, but they are very similar in the way they work. This page describes common behavior. Some assemblers stray from it. Refer to arch-specific documentation for details. # Initial setup Assemblers live in their arch-specific blkfs. To load it, you first need to run "ARCHM" to have arch-specific loaders, and then call your assembler loader (for example, "Z80A"). Loaded alone, an assembler will spit opcodes for a "live" tar- get, that is, the computer it's running on. As long as you don't relocate the code, you will be able to run it just fine, but if you need to relocate it, you will need to load XCOMP *before* you load your assembler so that you have the necessary tooling to craft relocatable binaries. See doc/cross for details. # Wrapping native code You will often want to wrap your native code in such a way that it can be used from within forth. You do that with CODE. CODE allows you to create a new word, but instead of compiling references to other words, you write native code directly. Example: CODE 1+ BC INCd, ;CODE This word can then be used like any other (and is of course very fast). Unlike the regular compiling process, you don't go in "compile mode" when you use CODE. You stay in regular INTERPRET mode. All CODE does is spit the proper word header. Be sure to read about your target platform in doc/code. These documents specify which registers are assigned to what role. # Usage To spit binary code, use opcode words such as "LDrr," in the Z80 assembler which spits LD in its "r1, r2" form. Unlike typical assemblers, operation arguments go before the opcode word, not after it. Therefore, the "LD A, B" you would write in a regular assembler becomes "A B LDrr," Those opcode words, of which there is a complete list in each arch-specific documentation, end with "," to indicate that their effect is to write (,) the corresponding opcode. The "argtype" suffix after each mnemonic is needed because the assembler doesn't auto-detect the op's form based on arguments. It has to be explicitly specified. Although efforts are made to keep those argtypes consistent across arches, there are differences. Arch-specific doc has precise definitions for those argtypes. For example, in Z80 asm, "r" is for 8-bit registers, "d" for 16-bit ones, "i" for immediate, "c" is for conditions. # Labels and flow Assemblers, of course, implement their "flow" ops (jumps) but these are often awkward to use directly. To help with that, Collapse OS has a unified "flow" interface: HAL (see doc/hal). The HAL implements these flow words: IFZ, .. ELSE, .. THEN, \ part 1 if Z is set, part 2 otherwise IFNZ, .. THEN, \ execute if Z is unset IFC, .. THEN, \ execute if C is set IFNC, .. THEN, \ execute if C is unset BEGIN, .. BR JRi, \ loop forever BEGIN, .. BR JRZi, \ loop if Z is set FJR JRi, .. THEN, \ unconditional forward jump This unified flow layer lives at B007 and is loaded with assemblers. This layer requires the assembler to supply these words (which are ofter simple aliases: JRi, off -- relative unconditional jump JRZ, off -- relative conditional jump if Z is set JRNZ, off -- relative conditional jump if Z is unset JRC, off -- relative conditional jump if C is set JRNC, off -- relative conditional jump if C is unset This is not related to flow, but for xcomp, these words are also defined by every assembler: JMPi, addr -- unconditional absolute jump JMP(i), addr -- unconditional indirect jump CALLi, addr -- unconditional absolute call i>, n -- push n to Parameter stack (i)>, addr -- push value at addr to Parameter Stack These words generate the appropriate native code to perform the described actions. These structured flow are elegant, but limited because they need to be symmetric. There is no way, for example, to jump out of an infinite loop using only those words. Labels can also be used with those flow words for more flexibility: LSET L1 .. L1 BR JRi, .. L1 JMPi, \ backward jumps FJR JRi, TO L1 .. L1 FMARK \ forward jump BEGIN, FJR JRi, TO L1 .. BR JRi, .. L1 FMARK \ exiting loop Labels are simple VALUEs. For example, you can create a label with "0 VALUE lblmylabel". If in an XCOMP context, make sure you declare your labels before XSTART. XCOMP pre-declares L1 L2 and L3 which can be used in local contexts.