AS31(1)

🌸 AS31 β€” an Intel 8031/8051 assembler πŸ’…

okay bestie, welcome to AS31(1), General Commands Manual edition β€” this is the assembler that takes your little 8031/8051 assembly and turns it into actual bytes. let's get into it 🫢

✨ NAME ✨

as31 β€” An Intel 8031/8051 assembler


πŸŽ€ SYNOPSIS πŸŽ€

as31 [-h] [-l] [-s] [-v] [-Aarg] [-Ffmt] [-Ofile] infile.asm

πŸ’– DESCRIPTION πŸ’–

So here's the vibe: as31 assembles infile.asm into one of several different output formats. The output lands in a file called infile.obj. and yes, the .asm extension is required β€” like, non-negotiable, the assembler will simply not play with you otherwise 😭


⭐ OPTIONS ⭐

Big rule first, no cap: the options must appear before the input file name. Both options are optional (iconic behavior honestly). And the text of each flag has to appear on the same argument as the flag. For example, -Fod is a valid argument, but -F od is not. spacing matters bestie, she's picky πŸ’…

  • -h β€” makes the assembler print out a verbose message describing its options. That message goes to standard error. so it's help, but make it stderr, iykyk.
  • -l β€” tells the assembler to also generate a listing file. The listing gets placed in infile.lst, where infile is the file being assembled. This option may appear anywhere before infile.asm, and it must occur isolated on the command line (no roomies, she's an only child).

The listing file shows the assembler generated code in hex, and up to 60 characters are retained from the source file. sixty. that's the number. respect it ✨

  • -s β€” makes the assembler write output to standard output. screen time, babes πŸ–₯️
  • -v β€” makes the assembler print a version number to standard output. cute little flex 🌈
  • -Aarg β€” specifies a format specific string which is passed to the format generator. Both the tdr format and the srecord formats use this option. (two formats, one flag, we love a versatile queen πŸ‘‘)
  • -Fformat β€” specifies the output format that is to be used.

Currently the only options available for this are:

  • hex β€” this format is the Intel HEX format which is expected by a number of EPROM programmers and the PAULMON debugger. For use with some programmers, the output file's extension may have to be changed to .HEX to be recognized by the programmer. No -A option is used. This format should be the default if no -F option is used. the main character of formats, honestly 🧚
  • tdr β€” this format generates an ASCII file of hex digits formatted in such a way, so that they can be read by tdr's debugger. An argument can be specified (see the -A option) which will pass a format specific string to the format generator. In this case, the argument string represents an offset to add to the location counter. This offset is specified in decimal and defaults to 64*1024 (0x10000). To specify an offset of 100, you would need -Ftdr -A100 when invoking the assembler.
watch the default here β€” it is not zero. it's 64*1024. tdr said "go big" πŸ’€
  • byte β€” this format is simply an address and a byte on each line, in ASCII. No -A option is used. minimalism, she ate πŸ’…
  • od β€” this format is similar to the output from od(1). The format consists of an address followed by sixteen hexadecimal bytes, followed by the equivalent ASCII. No -A option is used. sixteen bytes. very aligned. very demure πŸŽ€
  • srec2, srec3, srec4 β€” the srecord generator is capable of generating output with any one of 2, 3, or 4 byte addresses. The -A option can be used to set the base address offset, and the default here is 0x0000 (unlike tdr β€” yes, the two formats disagree about defaults, and that's just how it is 😭).
NOTE: This assembler allows for the output formats to be expanded to include many different output formats. so the list you're seeing? it can grow. the devs left room for more girlies 🌱
  • -Ofile β€” tells the assembler to write the output to a file. your bytes, your chosen destination πŸ’–

✨ ASSEMBLER INSTRUCTIONS ✨

okay so bestie, this assembler fully speaks standard 8031/8051 instruction formats, no cap. Below is the whole list of instructions plus their addressing modes, and every entry shows how many bytes it takes and how many cycles it eats. πŸ’…

  • ACALL addr11 β€” 2 bytes, 24 cycles
  • ADD A, #data8 β€” 2 bytes, 12 cycles
  • ADD A, @Ri β€” 1 bytes, 12 cycles
  • ADD A, Rn β€” 1 bytes, 12 cycles
  • ADD A, direct β€” 2 bytes, 12 cycles
  • ADDC A, #data8 β€” 2 bytes, 12 cycles
  • ADDC A, @Ri β€” 1 bytes, 12 cycles
  • ADDC A, Rn β€” 1 bytes, 12 cycles
  • ADDC A, direct β€” 2 bytes, 12 cycles
  • AJMP addr11 β€” 2 bytes, 24 cycles
  • ANL A, #data8 β€” 2 bytes, 12 cycles
  • ANL A, @Ri β€” 1 bytes, 12 cycles
  • ANL A, Rn β€” 1 bytes, 12 cycles
  • ANL A, direct β€” 2 bytes, 12 cycles
  • ANL C, /bit β€” 2 bytes, 24 cycles
  • ANL C, !bit β€” 2 bytes, 24 cycles
  • ANL C, bit β€” 2 bytes, 24 cycles
  • ANL direct, #data8 β€” 3 bytes, 24 cycles
  • ANL direct, A β€” 2 bytes, 12 cycles
  • CJNE @Ri, #data8, rel β€” 3 bytes, 24 cycles
  • CJNE A, #data8, rel β€” 3 bytes, 24 cycles
  • CJNE A, direct, rel β€” 3 bytes, 24 cycles
  • CJNE Rn, #data8, rel β€” 3 bytes, 24 cycles
  • CLR A β€” 1 bytes, 12 cycles
  • CLR C β€” 1 bytes, 12 cycles
  • CLR bit β€” 2 bytes, 12 cycles
  • CPL A β€” 1 bytes, 12 cycles
  • CPL C β€” 1 bytes, 12 cycles
  • CPL bit β€” 2 bytes, 12 cycles
  • DA A β€” 1 bytes, 12 cycles
  • DEC @Ri β€” 1 bytes, 12 cycles
  • DEC A β€” 1 bytes, 12 cycles
  • DEC DPTR β€” 1 bytes, 12 cycles
  • DEC Rn β€” 1 bytes, 12 cycles
  • DEC direct β€” 2 bytes, 12 cycles
  • DIV AB β€” 1 bytes, 48 cycles
  • DJNZ Rn, rel β€” 2 bytes, 24 cycles
  • DJNZ direct, rel β€” 3 bytes, 24 cycles
  • INC @Ri β€” 1 bytes, 12 cycles
  • INC A β€” 1 bytes, 12 cycles
  • INC DPTR β€” 1 bytes, 24 cycles
  • INC Rn β€” 1 bytes, 12 cycles
  • INC direct β€” 2 bytes, 12 cycles
  • JB bit, rel β€” 3 bytes, 24 cycles
  • JBC bit, rel β€” 3 bytes, 24 cycles
  • JC relative β€” 2 bytes, 24 cycles
  • JMP @A + DPTR β€” 1 bytes, 24 cycles
  • JMP @DPTR + A β€” 1 bytes, 24 cycles
  • JNB bit, rel β€” 3 bytes, 24 cycles
  • JNC relative β€” 2 bytes, 24 cycles
  • JNZ relative β€” 2 bytes, 24 cycles
  • JZ relative β€” 2 bytes, 24 cycles
  • LCALL addr16 β€” 3 bytes, 24 cycles
  • LJMP addr16 β€” 3 bytes, 24 cycles
  • MOV @Ri, #data8 β€” 2 bytes, 12 cycles
  • MOV @Ri, A β€” 1 bytes, 12 cycles
  • MOV @Ri, direct β€” 2 bytes, 24 cycles
  • MOV A, #data8 β€” 2 bytes, 12 cycles
  • MOV A, @Ri β€” 1 bytes, 12 cycles
  • MOV A, Rn β€” 1 bytes, 12 cycles
  • MOV A, direct β€” 2 bytes, 12 cycles
  • MOV C, bit β€” 2 bytes, 12 cycles
  • MOV DPTR, #data16 β€” 3 bytes, 24 cycles
  • MOV Rn, #data8 β€” 2 bytes, 12 cycles
  • MOV Rn, A β€” 1 bytes, 12 cycles
  • MOV Rn, direct β€” 2 bytes, 24 cycles
  • MOV bit, C β€” 2 bytes, 24 cycles
  • MOV direct, #data8 β€” 3 bytes, 24 cycles
  • MOV direct, @Ri β€” 2 bytes, 24 cycles
  • MOV direct, A β€” 2 bytes, 12 cycles
  • MOV direct, Rn β€” 2 bytes, 24 cycles
  • MOV direct, direct β€” 3 bytes, 24 cycles
  • MOVC A, @A + DPTR β€” 1 bytes, 24 cycles
  • MOVC A, @A + PC β€” 1 bytes, 24 cycles
  • MOVC A, @DPTR + A β€” 1 bytes, 24 cycles
  • MOVC A, @PC + A β€” 1 bytes, 24 cycles
  • MOVX @DPTR, A β€” 1 bytes, 12 cycles
  • MOVX @Ri, A β€” 1 bytes, 24 cycles
  • MOVX A, @DPTR β€” 1 bytes, 24 cycles
  • MOVX A, @Ri β€” 1 bytes, 24 cycles
  • MUL AB β€” 1 bytes, 48 cycles
  • NOP β€” 1 bytes, 12 cycles
  • ORL A, #data8 β€” 2 bytes, 12 cycles
  • ORL A, @Ri β€” 1 bytes, 12 cycles
  • ORL A, Rn β€” 1 bytes, 12 cycles
  • ORL A, direct β€” 2 bytes, 12 cycles
  • ORL C, /bit β€” 2 bytes, 24 cycles
  • ORL C, !bit β€” 2 bytes, 24 cycles
  • ORL C, bit β€” 2 bytes, 24 cycles
  • ORL direct, #data8 β€” 3 bytes, 24 cycles
  • ORL direct, A β€” 2 bytes, 12 cycles
  • POP direct β€” 2 bytes, 24 cycles
  • PUSH direct β€” 2 bytes, 24 cycles
  • RET β€” 1 bytes, 24 cycles
  • RETI β€” 1 bytes, 24 cycles
  • RL A β€” 1 bytes, 12 cycles
  • RLC A β€” 1 bytes, 12 cycles
  • RR A β€” 1 bytes, 12 cycles
  • RRC A β€” 1 bytes, 12 cycles
  • SETB A β€” 1 bytes, 12 cycles
  • SETB bit β€” 2 bytes, 12 cycles
  • SJMP relative β€” 2 bytes, 24 cycles
  • SUBB A, #data8 β€” 2 bytes, 12 cycles
  • SUBB A, @Ri β€” 1 bytes, 12 cycles
  • SUBB A, Rn β€” 1 bytes, 12 cycles
  • SUBB A, direct β€” 2 bytes, 12 cycles
  • SWAP A β€” 1 bytes, 12 cycles
  • XCH A, #data8 β€” 2 bytes, 12 cycles
  • XCH A, @Ri β€” 1 bytes, 12 cycles
  • XCH A, Rn β€” 1 bytes, 12 cycles
  • XCH A, direct β€” 2 bytes, 12 cycles
  • XCHD A, #data8 β€” 2 bytes, 12 cycles
  • XCHD A, @Ri β€” 1 bytes, 12 cycles
  • XCHD A, Rn β€” 1 bytes, 12 cycles
  • XCHD A, direct β€” 2 bytes, 12 cycles
  • XRL A, #data8 β€” 2 bytes, 12 cycles
  • XRL A, @Ri β€” 1 bytes, 12 cycles
  • XRL A, Rn β€” 1 bytes, 12 cycles
  • XRL A, direct β€” 2 bytes, 12 cycles
  • XRL direct, #data8 β€” 3 bytes, 12 cycles
  • XRL direct, A β€” 2 bytes, 12 cycles

πŸŽ€ ASSEMBLER DIRECTIVES πŸŽ€

bestie, as31 also ships with these assembler directives. they're like the little spells you sprinkle into your source, iykyk. ✨

.ORG expr

okay so this one tells the assembler to start assembling at the address specified by the expression expr. iconic, right?

⚠️ girlies beware: an error occurs if the assembler starts assembling over an address space that has previously been assembled into. so don't be messy with your addresses, fr fr. πŸ’€

.EQU symbol, expr

sets symbol to the value of expr. easy peasy. πŸ’–

but lowkey important: the value for expr must be known during the first pass, when the line containing the .EQU is encountered. so like, don't be out here referencing stuff that hasn't happened yet. 😭

.BYTE expr, expr, ...

assembles the bytes specified by the expression into memory. and guess what β€” a string may also be specified with this directive. slay! 🌸

.WORD expr, expr, ...

assembles the words specified by the expression into memory. ✨

the byte ordering used is that used by the 8031. periodt. πŸ‘‘

.FLAG symbol1, symbol.[0-7]

sets symbol1 to the bit address specified by the symbol.[0-7] expression. and where it says [0-7], that denotes a character between 0 and 7. πŸ¦‹

the resulting bit address is then checked to see if it is a valid bit address. vibe check, basically. πŸ’…

.END

this directive is ignored. that's it. that's the whole tea. πŸ™ˆ

.SKIP expr

adds the value of expr to the location counter. πŸŽ€

it's used to reserve a block of uninitialized data, and expr should be in bytes. no cap.

✨ LEXICAL CONVENTIONS ✨

okay bestie this is the part where we learn the grammar of the whole thing, like how you're even allowed to type numbers and words. lowkey important. let's go πŸ’…

  • Semicolons are a vibe killer β€” everything after a ; gets ignored all the way until a newline shows up. so comment away, queen. πŸ’¬
  • Numbers default to decimal, unless the number starts with one of these little prefix situations:
    • 0x or 0X β€” hex time, babes. like 0x00ff ✨
    • 0b or 0B β€” binary, just 1's and 0's. like 0b1100110010 🧚
    • 0 β€” boom, that's octal. like 0377
  • Numbers also default to decimal unless they end with one of these characters (suffix squad):
    • b or B β€” binary! but only if 0x wasn't used up there. like 1010101b
    • h or H β€” always hex. BUT if the first character is non-numerical you have to specify either 0x or 0 first. this is so the assembler doesn't get confused and think your hex number is a symbol (she's dramatic like that 😭). for example: 0ffh, 0xffh, 0XffH, 20h, 0x20 and 020h are all valid ways to specify a hexdigit. but these are not: ffh, 0ff.
    • d or D β€” forces the number to decimal. unless 0X was used. like 129d
    • o or O β€” makes the number get interpreted as octal. like 377o
  • Character constants go in single quotes like 'c' where c is some character. \b, \n, \r, \t, \' and \0 are valid too. and you can drop a character constant literally anywhere an integer value would fit. slay πŸ’–
  • Strings are a set of characters wrapped in double quotes "". a string is only valid with the .BYTE directive, bestie, don't try it anywhere else. \b, \n, \r, \t and \" are also valid escapes. but \0 is not. πŸ™ˆ
  • Instructions, directives, and these specific symbols: R0, R1, R2, R3, R4, R5, R6, R7, A, AB, and C β€” you can type all of them in upper or lower case and the assembler will not be confused, no cap. These words however cannot be defined as a user symbol. any user symbol you make keeps its case exactly as written, so foo and Foo are different symbols, but addc is the same as aDdC. πŸ‘‘
  • A symbol can be any alpha numerical character plus the underscore ('_'). cute and simple.
  • Expressions are accepted in most places where a value or a symbol is needed. an expression is made of the following operators. all of them evaluate to integer objects (higher precedence operators listed first, iykyk):
    • - β€” Unary minus
    • & β€” Bit-wise AND.
    • | β€” Bit-Wise OR.
    • * β€” Integer multiplication.
    • / β€” Integer division
    • % β€” Integer modulus
    • + β€” Integer addition.
    • - β€” Integer subtraction.
  • And one extra special icon: the symbol '*' may be used to represent the current location counter. main character energy, honestly ⭐

🌈 EXAMPLES 🌈

below is a sample assembly program. it's giving blinky lights. it's giving art. πŸŽ€

                .org    0
start:          mov     P3, #0xff       ; use alternate fns on P3
                                        ; leds on P1 are inverted.
                setb    F0              ; climbing up
                mov     A, #0x01        ; initial bit

write:          cpl     A               ; write it
                mov     P1, A
                cpl     A
                acall   delay
                jb      F0, climbup     ; climbing which way?

climbdn:        rr      A               ; down - shift right
                jnb     ACC.0, write    ; back for more
                setb    F0
                ajmp    write

climbup:        rl      A               ; up - shift left
                jnb     ACC.7, write    ; back for more
                clr     F0
                ajmp    write
                .end                    ; this directive ignored.

πŸ’œ AUTHORS πŸ’œ

these two literally built the thing, show some respect bestie 🫢

  • Ken Stauffer (University of Calgary) <stauffer@cpsc.ucalgary.ca>
  • Martin Langer <martin-langer@gmx.de>

and that's the whole page, bestie!! you made it to the end, I'm so proud of you, go forth and assemble with your whole chest πŸ’–βœ¨ this was the AS31(1) manual page, mwah, bye πŸŽ€πŸ’…πŸŒŸ