.Dd 26 February, 2024 .Dt U8ASM 5 .Os Ahoy 1.0.0 .Sh NAME .Nm c8asm .Nd the c8 assembly dialect .Sh DESCRIPTION The .Nm assembly dialect is the language understood by the .Xr c8asm 1 assembler. It is a small language consisting of only the few instructions and syntax elements described in this manual. A basic program to display the number 69 followed by an exclamation-mark on the screen may look as follows: .Bd -literal -offset indent ; Draw the sprite for ‘6’ ld v2 6 hex v2 drw v0 v1 5 ; Draw the sprite for ‘9’ ld v2 9 hex v2 add v0 5 ; Offset the X position by 5 drw v0 v1 5 ; Draw the sprite for ‘!’ ld i exclamation_sprite add v0 5 drw v0 v1 5 ; Infinite loop loop: jp loop exclamation_sprite: db 0b1000'0000 db 0b1000'0000 db 0b1000'0000 db 0b0000'0000 db 0b1000'0000 .Ed .Sh LANGUAGE SYNTAX .Ss Encoding All .Nm documents must be UTF-8 encoded. No other encodings are valid. .Ss Whitespace Syntax elements are often separated by whitespace. When mentioned in this document, .Sq whitespace refers to all Unicode codepoints with the property Pattern_White_Space. .Ss Case Unlike most assembly dialects, .Nm is case-sensitive. This means that the labels .Ql .foo and .Ql .FOO are not interchangeable and neither are the instructions .Ql add and .Ql ADD . .Ss Labels Labels are a way to assign names to a particular memory address. They’re useful for referencing locations of sprites, or instructions to jump to. .Pp A label is composed of a Unicode codepoint with the property XID_Start, followed by zero-or-more Unicode codepoints with the property XID_Continue. In simple terms this means labels follow the same syntax rules as most modern programming languages. As an extension to the Unicode specification labels may also begin with an underscore .Pq Sq _ . .Pp All labels must be terminated by any amount of whitespace and a colon .Pq Sq \&: . .Pp By default labels are globally scoped. This means that if you define the label .Ql foo , you’ll be able to reference that label from any file in your project. To define a label local to the current file you can prefix it with a period. .Ss Instructions The following is a list of available instructions in .Nm , and a description of their behavior. .Pp The following terms are used in this section: .Pp .Bl -tag -compact -width "nibble, byte, and addr" .It vx and vy arbitrary v-registers .Pq see: Sx Registers .It nibble, byte, and addr 4-, 8-, and 12-bit integer literals .It dt, st, i, and v0 the dt, st, i, and v0 registers .El .Pp The instructions are as follows: .Pp .Bl -tag -width Ds .It Ic add Ar i Ar vx , Ic add Ar vx Ar byte Add the values of the first- and second oprands and store the result in the first oprand. .It Ic add Ar vx Ar vy Add the values of .Ar vx and .Ar vy and store the result in .Ar vx. If the result is greater than 255 then .Ar vf is set to 1, otherwise 0. .It Ic and Ar vx Ar vy Perform a bitwise-AND of .Ar vx and .Ar vy and store the result in .Ar vx . .It Ic bcd Ar vx Store the hundreds-, tens-, and ones-digit of the BCD representation of the value in .Ar vx to the memory addresses stored in .Va i , .Va i+1 , and .Va i+2 . .It Ic call Ar addr Push the current address to the top of the callstack and set the instruction pointer to .Ar addr . .It Ic cls Clear the display. .It Ic db Ar byte ... Insert the byte arguments literally into the assembled binary. .It Ic drw Ar vx Ar vy Ar nibble Draw the sprite pointed to by the .Va i register at the position .Pq Va vx , Va vy with a height of .Ar nibble . .It Ic hex Ar vx Set the .Va i register to the address of the hexadecimal sprite corresponding to the value of .Ar vx . .It Ic jp Ar addr Set the instruction pointer to .Ar addr . .It Ic jp Ar v0 Ar addr Set the instruction pointer to .Ar v0 + .Ar addr . .It Ic ld Ar dt Ar vx , Ic ld Ar i Ar addr , Ic ld Ar st Ar vx , Ic ld Ar vx Ar byte , Ic ld Ar vx Ar dt , Ic ld Ar vx Ar vy Store the value of the second oprand into the first oprand. .It Ic ld Ar vx Ar k Block until the user presses a key, and store the value of the key pressed into .Ar vx . .It Ic or Ar vx Ar vy Perform a bitwise-OR of .Ar vx and .Ar vy and store the result in .Ar vx . .It Ic ret Pop an address off the top of the callstack and set the instruction pointer to that location. .It Ic rnd Ar vx Ar byte Set .Ar vx to the bitwise-AND of a randomly-generated byte and the given .Ar byte . .It Ic rstr Ar vx Reads data starting at the memory address stored in the .Va i register into the registers .Va v0 though to .Ar vx inclusive. .Pp The .Va i register is incremented by .Ar x . .It Ic se Ar vx Ar byte , Ic se Ar vx Ar vy Skip the next instruction if the two oprands are equal. .It Ic shl Ar vx Left-shift .Ar vx by 1 and store the result in .Ar vx . If the most-significant-byte of .Ar vx was 1 .Va vf is set to 1 otherwise 0. .It Ic shr Ar vx Right-shift .Ar vx by 1 and store the result in .Ar vx . If the least-significant-byte of .Ar vx was 1 .Va vf is set to 1 otherwise 0. .It Ic sknp Ar vx Skip the next instruction if the key with the value of .Ar vx is not pressed. .It Ic skp Ar vx Skip the next instruction if the key with the value of .Ar vx is pressed. .It Ic sne Ar vx Ar byte , Ic sne Ar vx Ar vy Skip the next instruction if the two oprands are not equal. .It Ic stor Ar vx Stores the values of the registers .Va v0 through .Ar vx inclusive starting at the memory address stored in the .Va i register. .Pp The .Va i register is incremented by .Ar x . .It Ic subn Ar vx Ar vy Subtract .Ar vx from .Ar vy and store the result in .Ar vx . If .Ar vy was greater than .Ar vx then .Va vf is set to 1 otherwise 0. .It Ic sub Ar vx Ar vy Subtract .Ar vy from .Ar vx and store the result in .Ar vx . If .Ar vx was greater than .Ar vy then .Va vf is set to 1 otherwise 0. .It Ic sys Ar addr Jump to a machine-code routine at the address .Ar addr . .Pp Most interpreters completely ignore this instruction. .It Ic xor Ar vx Ar vy Perform a bitwise-XOR of .Ar vx and .Ar vy and store the result in .Ar vx . .El .Ss Registers The following registers are available for use in .Nm programs: .TS box; c | c l | r. Name Size (Bits) _ v0–vf 8 i 16 dt 8 st 8 .TE .Pp The .Va v0 Ns – Ns Va ve registers are general-purpose registers intended for use by the programmer. The .Va vf register is also a general-purpose register but is overriden by various instructions which utilize it as a flags register. .Pp The .Va i register is intended to be used to store 12-bit memory addresses. .Pp The .Va dt and .Va st registers are special registers. When non-zero they are decremented by 1 at a rate of 60 Hz. Additionally, when the .Va st register is non-zero, a monotone beep is played. .Ss Integer Literals The .Nm language supports non-negative binary-, octal-, decimal-, and hexadecimal integer literals. Integer literals are prefixed by a literal .Sq 0 and a lowercase base-specifier, but this prefix is optional for base-10 integers. The base-specifiers are as follows: .Pp .Bl -tag -compact -width Ds .It b binary .It o octal .It d decimal .It x hexadecimal .El .Pp The following table shows how different numbers can be represented in different bases: .Pp .TS box; c | c | c | c r | r | r | r. Binary Octal Decimal Hexadecimal _ 0b01100000 0o140 96 0x60 0b00010011 0o023 19 0x13 0b01111111 0o177 127 0x7F 0b00111010 0o072 58 0x3A .TE .Pp An apostrophe .Pq Sq \(aq can also be included anywhere in an integer literal .Em after the base-specifier as a digit-separator, such as in .Ql 0b1011\(aq1001 . .Ss Strings Strings are composed of an opening- and closing double quote .Pq Sq \(dq with zero-or-more bytes between them. Strings can only be used as an argument to the .Ql db instruction and they expand to a sequence of bytes representing their contents. .Pp The following two lines are equivalent: .Bd -literal -offset indent db "foo" db 0x66 0x6F 0x6F .Ed .Sh SEE ALSO .Xr ahoy 1 , .Xr c8asm 1 , .Xr c8dump 1 .Rs .%A Thomas P. Greene .%D 30th August, 1997 .%R Cowgod’s Chip-8 Technical Reference .%U http://devernay.free.fr/hacks/chip8/C8TECH10.HTM .Re .Sh AUTHORS .An Thomas Voss Aq Mt mail@thomasvoss.com