.ft CW.ta 8n +8n +8n +8n +8n +8n +8n.ft.TLA Manual for the Plan 9 assembler.AU.I "Rob Pike".AIrob@plan9.bell-labs.com.SHMachines.PPThere is an assembler for each of the MIPS, SPARC, Intel 386,Motorola 68020 and 68000, IBM Power PC, DEC Alpha, and ARM.The 68020 assembler,.CW 2a ,is the oldest and in many ways the prototype.The assemblers are really just variations of a single program:they share many properties such as left-to-right assignment order forinstruction operands and the synthesis of macro instructionssuch as.CW MOVEto hide the peculiarities of the load and store structure of the machines.To keep things concrete, the first part of this manual isspecifically about the 68020.At the end is a description of the differences amongthe other assemblers..ig.PPThe document, ``How to Use the Plan 9 C Compiler'', by Rob Pike,is a prerequisite for this manual....SHRegisters.PPAll pre-defined symbols in the assembler are upper-case.Data registers are.CW R0through.CW R7 ;address registers are.CW A0through.CW A7 ;floating-point registers are.CW F0through.CW F7 ..PPA pointer in.CW A6is used by the C compiler to point to data, enabling short addresses tobe used more often.The value of.CW A6is constant and must be set during C program initializationto the address of the externally-defined symbol.CW a6base ..PPThe following hardware registers are defined in the assembler; theirmeaning should be obvious given a 68020 manual:.CW CAAR ,.CW CACR ,.CW CCR ,.CW DFC ,.CW ISP ,.CW MSP ,.CW SFC ,.CW SR ,.CW USP ,and.CW VBR ..PPThe assembler also defines several pseudo-registers thatmanipulate the stack:.CW FP ,.CW SP ,and.CW TOS ..CW FPis the frame pointer, so.CW 0(FP)is the first argument,.CW 4(FP)is the second, and so on..CW SPis the local stack pointer, where automatic variables are held(SP is a pseudo-register only on the 68020);.CW 0(SP)is the first automatic, and so on as with.CW FP .Finally,.CW TOSis the top-of-stack register, used for pushing parameters to procedures,saving temporary values, and so on..PPThe assembler and loader track these pseudo-registers sothe above statements are true regardless of what has beenpushed on the hardware stack, pointed to by.CW A7 .The name.CW A7refers to the hardware stack pointer, but beware of mixed use of.CW A7and the above stack-related pseudo-registers, which will cause trouble.Note, too, that the.CW PEAinstruction is observed by the loader toalter SP and thus will insert a corresponding pop before all returns.The assembler accepts a label-like name to be attached to.CW FPand.CW SPuses, such as.CW p+0(FP) ,to help document that.CW pis the first argument to a routine.The name goes in the symbol table but has no significance to the resultof the program..SHReferring to data.PPAll external references must be made relative to some pseudo-register,either.CW PC(the virtual program counter) or.CW SB(the ``static base'' register)..CW PCcounts instructions, not bytes of data.For example, to branch to the second following instruction, that is,to skip one instruction, one may write.P1 BRA 2(PC).P2Labels are also allowed, as in.P1 BRA return NOPreturn: RTS.P2When using labels, there is no.CW (PC)annotation..PPThe pseudo-register.CW SBrefers to the beginning of the address space of the program.Thus, references to global data and procedures are written asoffsets to.CW SB ,as in.P1 MOVL $array(SB), TOS.P2to push the address of a global array on the stack, or.P1 MOVL array+4(SB), TOS.P2to push the second (4-byte) element of the array.Note the use of an offset; the complete list of addressing modes is given below.Similarly, subroutine calls must use.CW SB :.P1 BSR exit(SB).P2File-static variables have syntax.P1 local<>+4(SB).P2The.CW <>will be filled in at load time by a unique integer..PPWhen a program starts, it must execute.P1 MOVL $a6base(SB), A6.P2before accessing any global data.(On machines such as the MIPS and SPARC that cannot load a registerin a single instruction, constants are loaded through the static baseregister. The loader recognizes code that initializes the staticbase register and treats it specially. You must be careful, however,not to load large constants on such machines when the static baseregister is not set up, such as early in interrupt routines.).SHExpressions.PPExpressions are mostly what one might expect.Where an offset or a constant is expected,a primary expression with unary operators is allowed.A general C constant expression is allowed in parentheses..PPSource files are preprocessed exactly as in the C compiler, so.CW #defineand.CW #includework..SHAddressing modes.PPThe simple addressing modes are shared by all the assemblers.Here, for completeness, follows a table of all the 68020 addressing modes,since that machine has the richest set.In the table,.CW ois an offset, which if zero may be elided, and.CW dis a displacement, which is a constant between -128 and 127 inclusive.Many of the modes listed have the same name;scrutiny of the format will show what default is being applied.For instance, indexed mode with no address register supplied operatesas though a zero-valued register were used.For "offset" read "displacement."For "\f(CW.s\fP" read one of.CW .L ,or.CW .Wfollowed by.CW *1 ,.CW *2 ,.CW *4 ,or.CW *8to indicate the size and scaling of the data..IP.TSl lfCW.data register R0address register A0floating-point register F0special names CAAR, CACR, etc.constant $confloating point constant $fconexternal symbol name+o(SB)local symbol name<>+o(SB)automatic symbol name+o(SP)argument name+o(FP)address of external $name+o(SB)address of local $name<>+o(SB)indirect post-increment (A0)+indirect pre-decrement -(A0)indirect with offset o(A0)indexed with offset o()(R0.s)indexed with offset o(A0)(R0.s)external indexed name+o(SB)(R0.s)local indexed name<>+o(SB)(R0.s)automatic indexed name+o(SP)(R0.s)parameter indexed name+o(FP)(R0.s)offset indirect post-indexed d(o())(R0.s)offset indirect post-indexed d(o(A0))(R0.s)external indirect post-indexed d(name+o(SB))(R0.s)local indirect post-indexed d(name<>+o(SB))(R0.s)automatic indirect post-indexed d(name+o(SP))(R0.s)parameter indirect post-indexed d(name+o(FP))(R0.s)offset indirect pre-indexed d(o()(R0.s))offset indirect pre-indexed d(o(A0))offset indirect pre-indexed d(o(A0)(R0.s))external indirect pre-indexed d(name+o(SB))external indirect pre-indexed d(name+o(SB)(R0.s))local indirect pre-indexed d(name<>+o(SB))local indirect pre-indexed d(name<>+o(SB)(R0.s))automatic indirect pre-indexed d(name+o(SP))automatic indirect pre-indexed d(name+o(SP)(R0.s))parameter indirect pre-indexed d(name+o(FP))parameter indirect pre-indexed d(name+o(FP)(R0.s)).TE.in.SHLaying down data.PPPlacing data in the instruction stream, say for interrupt vectors, is easy:the pseudo-instructions.CW LONGand.CW WORD(but not.CW BYTE )lay down the value of their single argument, of the appropriate size,as if it were an instruction:.P1 LONG $12345.P2places the long 12345 (base 10)in the instruction stream.(On most machines,the only such operator is.CW WORDand it lays down 32-bit quantities.The 386 has all three:.CW LONG ,.CW WORD ,and.CW BYTE .The AMD64 adds.CW QUADfor 64-bit values.).PPPlacing information in the data section is more painful.The pseudo-instruction.CW DATAdoes the work, given two arguments: an address at which to place the item,including its size,and the value to place there. For example, to define a character array.CW arraycontaining the characters.CW abcand a terminating null:.P1 DATA array+0(SB)/1, $'a' DATA array+1(SB)/1, $'b' DATA array+2(SB)/1, $'c' GLOBL array(SB), $4.P2or.P1 DATA array+0(SB)/4, $"abc\ez" GLOBL array(SB), $4.P2The.CW /1defines the number of bytes to define,.CW GLOBLmakes the symbol global, and the.CW $4says how many bytes the symbol occupies.Uninitialized data is zeroed automatically.The character.CW \ezis equivalent to the C.CW \e0.The string in a.CW DATAstatement may contain a maximum of eight bytes;build larger strings piecewise.Two pseudo-instructions,.CW DYNTand.CW INIT ,allow the (obsolete) Alef compilers to build dynamic type information during the loadphase.The.CW DYNTpseudo-instruction has two forms:.P1 DYNT , ALEF_SI_5+0(SB) DYNT ALEF_AS+0(SB), ALEF_SI_5+0(SB).P2In the first form,.CW DYNTdefines the symbol to be a small unique integer constant, chosen by the loader,which is some multiple of the word size. In the second form,.CW DYNTdefines the second symbol in the same way,places the address of the most recentlydefined text symbol in the array specified by the first symbol at theindex defined by the value of the second symbol,and then adjusts the size of the array accordingly..PPThe.CW INITpseudo-instruction takes the same parameters as a.CW DATAstatement. Its symbol is used as the base of an array and thedata item is installed in the array at the offset specified by the most recent.CW DYNTpseudo-instruction.The size of the array is adjusted accordingly.The.CW DYNTand.CW INITpseudo-instructions are not implemented on the 68020..SHDefining a procedure.PPEntry points are defined by the pseudo-operation.CW TEXT ,which takes as arguments the name of the procedure (including the ubiquitous.CW (SB) )and the number of bytes of automatic storage to pre-allocate on the stack,which will usually be zero when writing assembly language programs.On machines with a link register, such as the MIPS and SPARC,the special value -4 instructs the loader to generate no PC saveand restore instructions, even if the function is not a leaf.Here is a complete procedure that returns the sumof its two arguments:.P1TEXT sum(SB), $0 MOVL arg1+0(FP), R0 ADDL arg2+4(FP), R0 RTS.P2An optional middle argumentto the.CW TEXTpseudo-op is a bit field of options to the loader.Setting the 1 bit suspends profiling the function when profiling is enabled for the rest ofthe program.For example,.P1TEXT sum(SB), 1, $0 MOVL arg1+0(FP), R0 ADDL arg2+4(FP), R0 RTS.P2will not be profiled; the first version above would be.Subroutines with peculiar state, such as system call routines,should not be profiled..PPSetting the 2 bit allows multiple definitions of the same.CW TEXTsymbol in a program; the loader will place only one such function in the image.It was emitted only by the Alef compilers..PPSubroutines to be called from C should place their result in.CW R0 ,even if it is an address.Floating point values are returned in.CW F0 .Functions that return a structure to a C programreceive as their first argument the address of the location tostore the result;.CW R0is unused in the calling protocol for such procedures.A subroutine is responsible for saving its own registers,and therefore is free to use any registers without saving them (``caller saves'')..CW A6and.CW A7are the exceptions as described above..SHWhen in doubt.PPIf you get confused, try using the.CW -Soption to.CW 2cand compiling a sample program.The standard output is valid input to the assembler..SHInstructions.PPThe instruction set of the assembler is not identical to thatof the machine.It is chosen to match what the compiler generates, augmentedslightly by specific needs of the operating system.For example,.CW 2adoes not distinguish between the various forms of.CW MOVEinstruction: move quick, move address, etc. Instead the contextdoes the job. For example,.P1 MOVL $1, R1 MOVL A0, R2 MOVW SR, R3.P2generates official.CW MOVEQ ,.CW MOVEA ,and.CW MOVESRinstructions.A number of instructions do not have the syntax necessary to specifytheir entire capabilities. Notable examples are the bitfieldinstructions, themultiply and divide instructions, etc.For a complete set of generated instruction names (in.CW 2anotation, not Motorola's) see the file.CW /sys/src/cmd/2c/2.out.h .Despite its name, this file contains an enumeration of theinstructions that appear in the intermediate files generatedby the compiler, which correspond exactly to lines of assembly language..PPThe MC68000 assembler,.CW 1a ,is essentially the same, honoring the appropriate subset of the instructionsand addressing modes.The definitions of these are, nonetheless, part of.CW 2.out.h ..SHLaying down instructions.PPThe loader modifies the code produced by the assembler and compiler.It folds branches,copies short sequences of code to eliminate branches,and discards unreachable code.The first instruction of every function is assumed to be reachable.The pseudo-instruction.CW NOP ,which you may see in compiler output,means no instruction at all, rather than an instruction that does nothing.The loader discards all.CW NOP 's..PPTo generate a trueLines 1–500 of 1394. Load more
.ft CW .ta 8n +8n +8n +8n +8n +8n +8n .ft .TL A Manual for the Plan 9 assembler .AU .I "Rob Pike" .AI rob@plan9.bell-labs.com .SH Machines .PP There is an assembler for each of the MIPS, SPARC, Intel 386, Motorola 68020 and 68000, IBM Power PC, DEC Alpha, and ARM. The 68020 assembler, .CW 2a , is the oldest and in many ways the prototype. The assemblers are really just variations of a single program: they share many properties such as left-to-right assignment order for instruction operands and the synthesis of macro instructions such as .CW MOVE to hide the peculiarities of the load and store structure of the machines. To keep things concrete, the first part of this manual is specifically about the 68020. At the end is a description of the differences among the other assemblers. .ig .PP The document, ``How to Use the Plan 9 C Compiler'', by Rob Pike, is a prerequisite for this manual. .. .SH Registers .PP All pre-defined symbols in the assembler are upper-case. Data registers are .CW R0 through .CW R7 ; address registers are .CW A0 through .CW A7 ; floating-point registers are .CW F0 through .CW F7 . .PP A pointer in .CW A6 is used by the C compiler to point to data, enabling short addresses to be used more often. The value of .CW A6 is constant and must be set during C program initialization to the address of the externally-defined symbol .CW a6base . .PP The following hardware registers are defined in the assembler; their meaning should be obvious given a 68020 manual: .CW CAAR , .CW CACR , .CW CCR , .CW DFC , .CW ISP , .CW MSP , .CW SFC , .CW SR , .CW USP , and .CW VBR . .PP The assembler also defines several pseudo-registers that manipulate the stack: .CW FP , .CW SP , and .CW TOS . .CW FP is the frame pointer, so .CW 0(FP) is the first argument, .CW 4(FP) is the second, and so on. .CW SP is the local stack pointer, where automatic variables are held (SP is a pseudo-register only on the 68020); .CW 0(SP) is the first automatic, and so on as with .CW FP . Finally, .CW TOS is the top-of-stack register, used for pushing parameters to procedures, saving temporary values, and so on. .PP The assembler and loader track these pseudo-registers so the above statements are true regardless of what has been pushed on the hardware stack, pointed to by .CW A7 . The name .CW A7 refers to the hardware stack pointer, but beware of mixed use of .CW A7 and the above stack-related pseudo-registers, which will cause trouble. Note, too, that the .CW PEA instruction is observed by the loader to alter SP and thus will insert a corresponding pop before all returns. The assembler accepts a label-like name to be attached to .CW FP and .CW SP uses, such as .CW p+0(FP) , to help document that .CW p is the first argument to a routine. The name goes in the symbol table but has no significance to the result of the program. .SH Referring to data .PP All external references must be made relative to some pseudo-register, either .CW PC (the virtual program counter) or .CW SB (the ``static base'' register). .CW PC counts instructions, not bytes of data. For example, to branch to the second following instruction, that is, to skip one instruction, one may write .P1 BRA 2(PC) .P2 Labels are also allowed, as in .P1 BRA return NOP return: RTS .P2 When using labels, there is no .CW (PC) annotation. .PP The pseudo-register .CW SB refers to the beginning of the address space of the program. Thus, references to global data and procedures are written as offsets to .CW SB , as in .P1 MOVL $array(SB), TOS .P2 to push the address of a global array on the stack, or .P1 MOVL array+4(SB), TOS .P2 to push the second (4-byte) element of the array. Note the use of an offset; the complete list of addressing modes is given below. Similarly, subroutine calls must use .CW SB : .P1 BSR exit(SB) .P2 File-static variables have syntax .P1 local<>+4(SB) .P2 The .CW <> will be filled in at load time by a unique integer. .PP When a program starts, it must execute .P1 MOVL $a6base(SB), A6 .P2 before accessing any global data. (On machines such as the MIPS and SPARC that cannot load a register in a single instruction, constants are loaded through the static base register. The loader recognizes code that initializes the static base register and treats it specially. You must be careful, however, not to load large constants on such machines when the static base register is not set up, such as early in interrupt routines.) .SH Expressions .PP Expressions are mostly what one might expect. Where an offset or a constant is expected, a primary expression with unary operators is allowed. A general C constant expression is allowed in parentheses. .PP Source files are preprocessed exactly as in the C compiler, so .CW #define and .CW #include work. .SH Addressing modes .PP The simple addressing modes are shared by all the assemblers. Here, for completeness, follows a table of all the 68020 addressing modes, since that machine has the richest set. In the table, .CW o is an offset, which if zero may be elided, and .CW d is a displacement, which is a constant between -128 and 127 inclusive. Many of the modes listed have the same name; scrutiny of the format will show what default is being applied. For instance, indexed mode with no address register supplied operates as though a zero-valued register were used. For "offset" read "displacement." For "\f(CW.s\fP" read one of .CW .L , or .CW .W followed by .CW *1 , .CW *2 , .CW *4 , or .CW *8 to indicate the size and scaling of the data. .IP .TS l lfCW. data register R0 address register A0 floating-point register F0 special names CAAR, CACR, etc. constant $con floating point constant $fcon external symbol name+o(SB) local symbol name<>+o(SB) automatic symbol name+o(SP) argument name+o(FP) address of external $name+o(SB) address of local $name<>+o(SB) indirect post-increment (A0)+ indirect pre-decrement -(A0) indirect with offset o(A0) indexed with offset o()(R0.s) indexed with offset o(A0)(R0.s) external indexed name+o(SB)(R0.s) local indexed name<>+o(SB)(R0.s) automatic indexed name+o(SP)(R0.s) parameter indexed name+o(FP)(R0.s) offset indirect post-indexed d(o())(R0.s) offset indirect post-indexed d(o(A0))(R0.s) external indirect post-indexed d(name+o(SB))(R0.s) local indirect post-indexed d(name<>+o(SB))(R0.s) automatic indirect post-indexed d(name+o(SP))(R0.s) parameter indirect post-indexed d(name+o(FP))(R0.s) offset indirect pre-indexed d(o()(R0.s)) offset indirect pre-indexed d(o(A0)) offset indirect pre-indexed d(o(A0)(R0.s)) external indirect pre-indexed d(name+o(SB)) external indirect pre-indexed d(name+o(SB)(R0.s)) local indirect pre-indexed d(name<>+o(SB)) local indirect pre-indexed d(name<>+o(SB)(R0.s)) automatic indirect pre-indexed d(name+o(SP)) automatic indirect pre-indexed d(name+o(SP)(R0.s)) parameter indirect pre-indexed d(name+o(FP)) parameter indirect pre-indexed d(name+o(FP)(R0.s)) .TE .in .SH Laying down data .PP Placing data in the instruction stream, say for interrupt vectors, is easy: the pseudo-instructions .CW LONG and .CW WORD (but not .CW BYTE ) lay down the value of their single argument, of the appropriate size, as if it were an instruction: .P1 LONG $12345 .P2 places the long 12345 (base 10) in the instruction stream. (On most machines, the only such operator is .CW WORD and it lays down 32-bit quantities. The 386 has all three: .CW LONG , .CW WORD , and .CW BYTE . The AMD64 adds .CW QUAD for 64-bit values.) .PP Placing information in the data section is more painful. The pseudo-instruction .CW DATA does the work, given two arguments: an address at which to place the item, including its size, and the value to place there. For example, to define a character array .CW array containing the characters .CW abc and a terminating null: .P1 DATA array+0(SB)/1, $'a' DATA array+1(SB)/1, $'b' DATA array+2(SB)/1, $'c' GLOBL array(SB), $4 .P2 or .P1 DATA array+0(SB)/4, $"abc\ez" GLOBL array(SB), $4 .P2 The .CW /1 defines the number of bytes to define, .CW GLOBL makes the symbol global, and the .CW $4 says how many bytes the symbol occupies. Uninitialized data is zeroed automatically. The character .CW \ez is equivalent to the C .CW \e0. The string in a .CW DATA statement may contain a maximum of eight bytes; build larger strings piecewise. Two pseudo-instructions, .CW DYNT and .CW INIT , allow the (obsolete) Alef compilers to build dynamic type information during the load phase. The .CW DYNT pseudo-instruction has two forms: .P1 DYNT , ALEF_SI_5+0(SB) DYNT ALEF_AS+0(SB), ALEF_SI_5+0(SB) .P2 In the first form, .CW DYNT defines the symbol to be a small unique integer constant, chosen by the loader, which is some multiple of the word size. In the second form, .CW DYNT defines the second symbol in the same way, places the address of the most recently defined text symbol in the array specified by the first symbol at the index defined by the value of the second symbol, and then adjusts the size of the array accordingly. .PP The .CW INIT pseudo-instruction takes the same parameters as a .CW DATA statement. Its symbol is used as the base of an array and the data item is installed in the array at the offset specified by the most recent .CW DYNT pseudo-instruction. The size of the array is adjusted accordingly. The .CW DYNT and .CW INIT pseudo-instructions are not implemented on the 68020. .SH Defining a procedure .PP Entry points are defined by the pseudo-operation .CW TEXT , which takes as arguments the name of the procedure (including the ubiquitous .CW (SB) ) and the number of bytes of automatic storage to pre-allocate on the stack, which will usually be zero when writing assembly language programs. On machines with a link register, such as the MIPS and SPARC, the special value -4 instructs the loader to generate no PC save and restore instructions, even if the function is not a leaf. Here is a complete procedure that returns the sum of its two arguments: .P1 TEXT sum(SB), $0 MOVL arg1+0(FP), R0 ADDL arg2+4(FP), R0 RTS .P2 An optional middle argument to the .CW TEXT pseudo-op is a bit field of options to the loader. Setting the 1 bit suspends profiling the function when profiling is enabled for the rest of the program. For example, .P1 TEXT sum(SB), 1, $0 MOVL arg1+0(FP), R0 ADDL arg2+4(FP), R0 RTS .P2 will not be profiled; the first version above would be. Subroutines with peculiar state, such as system call routines, should not be profiled. .PP Setting the 2 bit allows multiple definitions of the same .CW TEXT symbol in a program; the loader will place only one such function in the image. It was emitted only by the Alef compilers. .PP Subroutines to be called from C should place their result in .CW R0 , even if it is an address. Floating point values are returned in .CW F0 . Functions that return a structure to a C program receive as their first argument the address of the location to store the result; .CW R0 is unused in the calling protocol for such procedures. A subroutine is responsible for saving its own registers, and therefore is free to use any registers without saving them (``caller saves''). .CW A6 and .CW A7 are the exceptions as described above. .SH When in doubt .PP If you get confused, try using the .CW -S option to .CW 2c and compiling a sample program. The standard output is valid input to the assembler. .SH Instructions .PP The instruction set of the assembler is not identical to that of the machine. It is chosen to match what the compiler generates, augmented slightly by specific needs of the operating system. For example, .CW 2a does not distinguish between the various forms of .CW MOVE instruction: move quick, move address, etc. Instead the context does the job. For example, .P1 MOVL $1, R1 MOVL A0, R2 MOVW SR, R3 .P2 generates official .CW MOVEQ , .CW MOVEA , and .CW MOVESR instructions. A number of instructions do not have the syntax necessary to specify their entire capabilities. Notable examples are the bitfield instructions, the multiply and divide instructions, etc. For a complete set of generated instruction names (in .CW 2a notation, not Motorola's) see the file .CW /sys/src/cmd/2c/2.out.h . Despite its name, this file contains an enumeration of the instructions that appear in the intermediate files generated by the compiler, which correspond exactly to lines of assembly language. .PP The MC68000 assembler, .CW 1a , is essentially the same, honoring the appropriate subset of the instructions and addressing modes. The definitions of these are, nonetheless, part of .CW 2.out.h . .SH Laying down instructions .PP The loader modifies the code produced by the assembler and compiler. It folds branches, copies short sequences of code to eliminate branches, and discards unreachable code. The first instruction of every function is assumed to be reachable. The pseudo-instruction .CW NOP , which you may see in compiler output, means no instruction at all, rather than an instruction that does nothing. The loader discards all .CW NOP 's. .PP To generate a true