CRASM(1)

πŸ“¦
version 1.11 Β· 2 versions
, in ubuntu questing, ubuntu resolute, ubuntu stonking

πŸ’– CRASM(1) πŸ’–

okay bestie, sit down, hydrate, because this is the manual page for crasm β€” the Crasm-1.3 era one, section 1 of the manual. It's a cross assembler and it is genuinely so good at its job. Let's get into it. 🫢


✨ NAME ✨

crasm β€” Cross assembler for 6800/6801/6803/6502/65C02/Z80


πŸŽ€ SYNOPSIS πŸŽ€

crasm [-o codefile] [-slx] asmfile

So the whole vibe is: you hand crasm asmfile, your microprocessor program, and it assembles it into an output file codefile, written in Intel HEX or Motorola S Code format. You also get a program listing and a symbol table printed on standard output β€” free extras, no cap. πŸ’…

The current version of crasm can assemble programs for the 6800, 6801, 6803, 6502, 65C02, and Z80 processors. And if you wanna see the full list with your own eyes, just invoke crasm with no arguments and it prints it right out for you. ✨


πŸ’… OPTIONS πŸ’…

  • -o codefile β€” names your output file. No output file is produced without this option, so like... use it, bestie.
  • -s β€” disables warnings.
  • -l β€” disables program listing output.
  • -x β€” disables symbol table output.

🌸 SYNTAX 🌸

Every line of your assembly program needs to follow one of these templates. The brackets are just marking the optional parts, they're not real characters you type:

[;comment]
label = expression [;comment]
[label] mnemonic operand [;comment]
label[;comment]

Comments are introduced by a semicolon (;) and they run all the way to the end of the line. That's it, that's the whole comment system, iconic honestly.

Labels are identifiers made of up to 36 alphanumeric characters (period and underscore count as alphanumeric here). Labels cannot start with a digit. And crasm usually does not pay attention to what column your line components start in β€” it's very chill about that. The one exception: if a line contains only a label and possibly a comment, then that label must start in column zero. Like, column zero specifically. Don't fight it.

What the mnemonic and operand fields look like depends on which microprocessor you selected. A few mnemonics are valid for all processors, and those are the ones you use to give directives to the assembler. Everybody calls them "pseudo-mnemonics".

πŸ¦‹ Labels πŸ¦‹

Labels are identifiers representing:

  • an absolute address,
  • a relative address (position independent code),
  • a register,
  • a list of registers,
  • a specific bit at a specific address,
  • or a mnemonic.

Most labels are composed of at most 36 alphanumeric characters, periods (.) or underscores (_). Labels cannot start with a digit. They are case insensitive β€” so don't stress about your caps lock. Labels that start with a period (.) are local labels, and their scope is either limited to the macro they're defined in, or limited to the code segment delimited by the pseudo-mnemonics CODE or DUMMY.

The predefined "star" label (*) represents the current program counter β€” that is, the address where the next assembly code instruction will be encoded. Other predefined labels include all pseudo-mnemonics, all microprocessor specific mnemonics, and register names. πŸŽ€

πŸ“ Constants πŸ“

The assembler recognizes numerical constants expressed in decimal, hexadecimal, octal, binary, or ascii. Here's the menu:

  • decimal β€” format dddd β€” examples: 1234, 675, 12, 1, but not 0.12.
  • hexadecimal
    • $dddd β€” examples: $fd12, $2AC, $0.
    • ddddH β€” examples: 03H, 2da7H, 0FC84H, but not FC84H.
    • 0Xdddd β€” examples: 0x03, 0x2AC, 0Xfc84.
  • octal β€” format ddddQ β€” examples: 377Q, 012412Q.
  • binary
    • %dddd β€” examples: %01110110, %1100.
    • ddddB β€” examples: 01110110B, 1100B.
    • 0Bdddd β€” example: 0b1100
  • ascii
    • 'cccc' β€” examples: 'a', 'AB', '"', '\n', '\''.
    • "cccc" β€” examples: "\t", "\", "a'b".

🧚 Expressions 🧚

Just like labels, expressions can represent an absolute address (abs), a relative address for position independent code (rel), a register (reg), or a list of registers (reglist), or a reference to a specific bit at a specific address (bspec).

These are the operators it recognizes on expressions:

  • abs{abs} β†’ bspec β€” bit reference, e.g. pia{3}
  • ADDR(abs) β†’ abs β€” address from a bit reference
  • BIT(abs) β†’ abs β€” bit number from a bit reference
  • - abs β†’ abs β€” two's complement
  • ~ abs β†’ abs β€” one's complement
  • abs << abs β†’ abs β€” left shift
  • abs >> abs β†’ abs β€” right shift
  • HI(abs) β†’ abs β€” high byte ((abs>>8)&$ff)
  • LO(abs) β†’ abs β€” low byte (abs&$ff)
  • abs | abs β†’ abs β€” bitwise or
  • abs & abs β†’ abs β€” bitwise and
  • abs ^ abs β†’ abs β€” bitwise xor
  • abs * abs β†’ abs β€” multiplication
  • abs * abs β†’ abs β€” division
  • abs + abs β†’ abs β€” addition
  • rel + abs β†’ rel β€” addition
  • abs - abs β†’ abs β€” subtraction
  • rel - abs β†’ rel β€” subtraction
  • rel - rel β†’ abs β€” subtraction
  • reg - reg β†’ reglist β€” register range
  • reglist \ reg β†’ reglist β€” register list

That list is in order of decreasing precedence β€” so the stuff near the top binds tighter, okay? Parenthesis can be used to avoid ambiguities. And heads up: a warning is generated when an entire expression is surrounded with parenthesis and can be confused with a microprocessor addressing mode. πŸ‘€

Examples:

(base+$12) >> 8 & 0xff00
'A'-80H
(base+0x12)

The last example causes a warning because the parenthesis were not necessary and might suggest a microprocessor addressing mode. It's giving "extra for no reason" and crasm will notice.

All arithmetic expressions are evaluated on 32 bits. Arithmetic operations overflow silently β€” no drama, no message, nothing. The arithmetic values are then truncated to the size implied by the microprocessor mnemonic, and that truncation might cause a warning message.

Examples: all the following instructions

(6502)    lda #$1234
(6800)    ldaa $1234,x
(Z80)     ld (ix+0C2H),b

cause a warning

>>> WARNING: Operand overflow

However expression

$1123454 * 1298992

overflows silently. Make it make sense 😭

πŸ‘‘ Pseudo-mnemonics πŸ‘‘

The following pseudo-mnemonics are always recognized. Always always. πŸ’–

  • CPU cpuname β€” indicates the selected microprocessor type. This must appear before any microprocessor specific instruction. The possible values of cpuname are listed when you invoke crasm without arguments, and the current list includes 6800, 6801, 6803, 6502, 65C02, and Z80.
  • OUTPUT binformat β€” indicates the format of the output file. The argument binformat can take the value SCODE, for producing an output file using Motorola's S code, or HEX, for Intel's Hex format. The default depends on the selected microprocessor.
  • CODE β€” delimits the scope of local labels and introduces a program section.
  • DUMMY β€” delimits the scope of local labels and introduces a fake program section whose sole effect is to define labels without generating code.
  • label EQU expression / label = expression β€” define the value of label label. Labels defined using these directives can be redefined later in the program. (Redefine away, bestie.)
  • [label] DB expression[,...,expression] β€” insert the specified data bytes (8 bits).
  • [label] DW expression[,...,expression] β€” insert the specified data words (16 bits). The byte ordering depends on the selected microprocessor.
  • [label] DL expression[,...,expression] β€” insert the specified data longs (32 bits). The byte ordering depends on the selected microprocessor.
  • [label] DDB expression[,...,expression] β€” drops in the double bytes (that's 16 bits, bestie) for every expression you list. But watch out: the byte ordering is the opposite of the usual byte ordering for whichever microprocessor you've selected. Not a typo. It's just like that. πŸ’€
  • [label] ASC stringconstant β€” inserts the ascii representation of the string stringconstant. The string must be delimited by double quotes, no negotiating. And the C escape sequences \r, \n, \t, \0, \', \", and \\ are all recognized, so go off. ✨
  • [label] DS countexpr,[valexpr] β€” inserts countexpr bytes, every one of them holding the value valexpr. The default value is zero, so if you're feeling lazy you literally don't have to say anything. 🫢
  • [label] ALIGN EVEN
  • [label] ALIGN ODD β€” inserts a null byte specifically so the program counter lands on an even or an odd address. Alignment? Handled. πŸ’…
  • IF [expr1 [oper expr2]] … ELSE … ENDC β€” conditional assembly, the main character of pseudo-mnemonics πŸ‘‘. The argument of IF can be totally empty, can be a single expression expr1, or can be two expressions separated by a comparison operator: >, <, >=, <=, ==, !=, =, or <>. Here's the tea: the assembler processes the lines between the IF and the ELSE pseudo-mnemonics if the comparison expr1 oper expr2 is true, or if the single expression expr1 is nonzero. Otherwise it processes the lines sitting between the ELSE and the ENDC pseudo-mnemonics. Conditional assembly instructions can be nested, which is giving inception fr fr. And the ELSE part can be omitted entirely. Flexible icon. 🌸
  • label MACRO … ENDM β€” defines a brand new mnemonic called label that's equivalent to all the instructions living between the MACRO and ENDM pseudo-mnemonics. When you invoke the macro you can pass a list of comma separated operands, and inside the macro definition the character sequences \1, \2, ... \N get replaced by the supplied operands. The character sequence \# gets replaced by the number of supplied operands. And the character sequence \* gets replaced by the unparsed macro arguments. So much power in one little backslash, I can't. 😭
  • EXITM β€” this pseudo mnemonic can be used inside a macro definition to exit the macro early. It's lowkey iconic when you pair it with the conditional assembly pseudo-mnemonics. πŸŽ€
  • INCLUDE filename β€” forces the assembler to go process the file named filename right at the current point. Bring your friends. πŸ¦‹
  • LIST ON
  • LIST OFF β€” turns the production of a listing on or off. The default is on.
  • CLIST ON
  • CLIST OFF β€” turns the production of a listing on or off for the non active branches of a conditional assembly construct. The default is on.
  • ILIST ON
  • ILIST OFF β€” turns the production of a listing on or off for included files. The default is off.
  • MLIST ON
  • MLIST OFF β€” turns the production of a listing on or off for macro expansions. The default is off.
  • NAM title β€” provides the name title for the header of the listing pages. Name your pages, they deserve it. ✨
  • PAGE β€” starts a new listing page. Fresh page, fresh vibe. 🌈
  • PAGE lines,columns β€” specifies the size of a listing page, with lines and columns.
  • SKIP number β€” skips number lines. Just. Skips them. πŸ¦‹
  • FAIL message β€” generates an error message containing message. Yes bestie, you can make the assembler yell on purpose. πŸ”₯

🌟 EXAMPLE 🌟

Here's a small 6502 program, look at her go:

       cpu 6502
   cout = $fded ; display a character
      * = $300  ; assemble at $300
        code
   pstring  ldy #0
   .1       lda message,y
            beq .2
            jsr cout
            iny
   .2       bne .1
            rts
   message  asc "This is the message "
        code

πŸ’– CREDITS πŸ’–

Leon Bottou, September 1987. Absolute legend, we stan. πŸ‘‘


and that's the whole page, bestie!! πŸŽ€ this gorgeous thing is from Crasm-1.3, dated 1/9/1987 β€” go forth and assemble something iconic. mwah πŸ’…βœ¨

πŸ“¦ where this page comes from