rsc.io/go@v0.0.0-20150416155037-e040fd465409/doc/asm.html (about)

     1  <!--{
     2  	"Title": "A Quick Guide to Go's Assembler",
     3  	"Path":  "/doc/asm"
     4  }-->
     5  
     6  <h2 id="introduction">A Quick Guide to Go's Assembler</h2>
     7  
     8  <p>
     9  This document is a quick outline of the unusual form of assembly language used by the <code>gc</code>
    10  suite of Go compilers (<code>6g</code>, <code>8g</code>, etc.).
    11  The document is not comprehensive.
    12  </p>
    13  
    14  <p>
    15  The assembler is based on the input to the Plan 9 assemblers, which is documented in detail
    16  <a href="http://plan9.bell-labs.com/sys/doc/asm.html">on the Plan 9 site</a>.
    17  If you plan to write assembly language, you should read that document although much of it is Plan 9-specific.
    18  This document provides a summary of the syntax and
    19  describes the peculiarities that apply when writing assembly code to interact with Go.
    20  </p>
    21  
    22  <p>
    23  The most important thing to know about Go's assembler is that it is not a direct representation of the underlying machine.
    24  Some of the details map precisely to the machine, but some do not.
    25  This is because the compiler suite (see
    26  <a href="http://plan9.bell-labs.com/sys/doc/compiler.html">this description</a>)
    27  needs no assembler pass in the usual pipeline.
    28  Instead, the compiler emits a kind of incompletely defined instruction set, in binary form, which the linker
    29  then completes.
    30  In particular, the linker does instruction selection, so when you see an instruction like <code>MOV</code>
    31  what the linker actually generates for that operation might not be a move instruction at all, perhaps a clear or load.
    32  Or it might correspond exactly to the machine instruction with that name.
    33  In general, machine-specific operations tend to appear as themselves, while more general concepts like
    34  memory move and subroutine call and return are more abstract.
    35  The details vary with architecture, and we apologize for the imprecision; the situation is not well-defined.
    36  </p>
    37  
    38  <p>
    39  The assembler program is a way to generate that intermediate, incompletely defined instruction sequence
    40  as input for the linker.
    41  If you want to see what the instructions look like in assembly for a given architecture, say amd64, there
    42  are many examples in the sources of the standard library, in packages such as
    43  <a href="/pkg/runtime/"><code>runtime</code></a> and
    44  <a href="/pkg/math/big/"><code>math/big</code></a>.
    45  You can also examine what the compiler emits as assembly code:
    46  </p>
    47  
    48  <pre>
    49  $ cat x.go
    50  package main
    51  
    52  func main() {
    53  	println(3)
    54  }
    55  $ go tool 6g -S x.go        # or: go build -gcflags -S x.go
    56  
    57  --- prog list "main" ---
    58  0000 (x.go:3) TEXT    main+0(SB),$8-0
    59  0001 (x.go:3) FUNCDATA $0,gcargs·0+0(SB)
    60  0002 (x.go:3) FUNCDATA $1,gclocals·0+0(SB)
    61  0003 (x.go:4) MOVQ    $3,(SP)
    62  0004 (x.go:4) PCDATA  $0,$8
    63  0005 (x.go:4) CALL    ,runtime.printint+0(SB)
    64  0006 (x.go:4) PCDATA  $0,$-1
    65  0007 (x.go:4) PCDATA  $0,$0
    66  0008 (x.go:4) CALL    ,runtime.printnl+0(SB)
    67  0009 (x.go:4) PCDATA  $0,$-1
    68  0010 (x.go:5) RET     ,
    69  ...
    70  </pre>
    71  
    72  <p>
    73  The <code>FUNCDATA</code> and <code>PCDATA</code> directives contain information
    74  for use by the garbage collector; they are introduced by the compiler.
    75  </p> 
    76  
    77  <!-- Commenting out because the feature is gone but it's popular and may come back.
    78  
    79  <p>
    80  To see what gets put in the binary after linking, add the <code>-a</code> flag to the linker:
    81  </p>
    82  
    83  <pre>
    84  $ go tool 6l -a x.6        # or: go build -ldflags -a x.go
    85  codeblk [0x2000,0x1d059) at offset 0x1000
    86  002000	main.main            | (3)	TEXT	main.main+0(SB),$8
    87  002000	65488b0c25a0080000   | (3)	MOVQ	2208(GS),CX
    88  002009	483b21               | (3)	CMPQ	SP,(CX)
    89  00200c	7707                 | (3)	JHI	,2015
    90  00200e	e83da20100           | (3)	CALL	,1c250+runtime.morestack00
    91  002013	ebeb                 | (3)	JMP	,2000
    92  002015	4883ec08             | (3)	SUBQ	$8,SP
    93  002019	                     | (3)	FUNCDATA	$0,main.gcargs·0+0(SB)
    94  002019	                     | (3)	FUNCDATA	$1,main.gclocals·0+0(SB)
    95  002019	48c7042403000000     | (4)	MOVQ	$3,(SP)
    96  002021	                     | (4)	PCDATA	$0,$8
    97  002021	e8aad20000           | (4)	CALL	,f2d0+runtime.printint
    98  002026	                     | (4)	PCDATA	$0,$-1
    99  002026	                     | (4)	PCDATA	$0,$0
   100  002026	e865d40000           | (4)	CALL	,f490+runtime.printnl
   101  00202b	                     | (4)	PCDATA	$0,$-1
   102  00202b	4883c408             | (5)	ADDQ	$8,SP
   103  00202f	c3                   | (5)	RET	,
   104  ...
   105  </pre>
   106  
   107  -->
   108  
   109  <h3 id="symbols">Symbols</h3>
   110  
   111  <p>
   112  Some symbols, such as <code>PC</code>, <code>R0</code> and <code>SP</code>, are predeclared and refer to registers.
   113  There are two other predeclared symbols, <code>SB</code> (static base) and <code>FP</code> (frame pointer).
   114  All user-defined symbols other than jump labels are written as offsets to these pseudo-registers.
   115  </p>
   116  
   117  <p>
   118  The <code>SB</code> pseudo-register can be thought of as the origin of memory, so the symbol <code>foo(SB)</code>
   119  is the name <code>foo</code> as an address in memory.
   120  This form is used to name global functions and data.
   121  Adding <code>&lt;&gt;</code> to the name, as in <code>foo&lt;&gt;(SB)</code>, makes the name
   122  visible only in the current source file, like a top-level <code>static</code> declaration in a C file.
   123  </p>
   124  
   125  <p>
   126  The <code>FP</code> pseudo-register is a virtual frame pointer
   127  used to refer to function arguments.
   128  The compilers maintain a virtual frame pointer and refer to the arguments on the stack as offsets from that pseudo-register.
   129  Thus <code>0(FP)</code> is the first argument to the function,
   130  <code>8(FP)</code> is the second (on a 64-bit machine), and so on.
   131  When referring to a function argument this way, it is conventional to place the name
   132  at the beginning, as in <code>first_arg+0(FP)</code> and <code>second_arg+8(FP)</code>.
   133  Some of the assemblers enforce this convention, rejecting plain <code>0(FP)</code> and <code>8(FP)</code>.
   134  For assembly functions with Go prototypes, <code>go</code> <code>vet</code> will check that the argument names
   135  and offsets match.
   136  On 32-bit systems, the low and high 32 bits of a 64-bit value are distinguished by adding
   137  a <code>_lo</code> or <code>_hi</code> suffix to the name, as in <code>arg_lo+0(FP)</code> or <code>arg_hi+4(FP)</code>.
   138  If a Go prototype does not name its result, the expected assembly name is <code>ret</code>.
   139  </p>
   140  
   141  <p>
   142  The <code>SP</code> pseudo-register is a virtual stack pointer
   143  used to refer to frame-local variables and the arguments being
   144  prepared for function calls.
   145  It points to the top of the local stack frame, so references should use negative offsets
   146  in the range [−framesize, 0):
   147  <code>x-8(SP)</code>, <code>y-4(SP)</code>, and so on.
   148  On architectures with a real register named <code>SP</code>, the name prefix distinguishes
   149  references to the virtual stack pointer from references to the architectural <code>SP</code> register.
   150  That is, <code>x-8(SP)</code> and <code>-8(SP)</code> are different memory locations:
   151  the first refers to the virtual stack pointer pseudo-register, while the second refers to the
   152  hardware's <code>SP</code> register.
   153  </p>
   154  
   155  <p>
   156  Instructions, registers, and assembler directives are always in UPPER CASE to remind you
   157  that assembly programming is a fraught endeavor.
   158  (Exception: the <code>g</code> register renaming on ARM.)
   159  </p>
   160  
   161  <p>
   162  In Go object files and binaries, the full name of a symbol is the 
   163  package path followed by a period and the symbol name:
   164  <code>fmt.Printf</code> or <code>math/rand.Int</code>.
   165  Because the assembler's parser treats period and slash as punctuation,
   166  those strings cannot be used directly as identifier names.
   167  Instead, the assembler allows the middle dot character U+00B7
   168  and the division slash U+2215 in identifiers and rewrites them to
   169  plain period and slash.
   170  Within an assembler source file, the symbols above are written as
   171  <code>fmt·Printf</code> and <code>math∕rand·Int</code>.
   172  The assembly listings generated by the compilers when using the <code>-S</code> flag
   173  show the period and slash directly instead of the Unicode replacements
   174  required by the assemblers.
   175  </p>
   176  
   177  <p>
   178  Most hand-written assembly files do not include the full package path
   179  in symbol names, because the linker inserts the package path of the current
   180  object file at the beginning of any name starting with a period:
   181  in an assembly source file within the math/rand package implementation,
   182  the package's Int function can be referred to as <code>·Int</code>.
   183  This convention avoids the need to hard-code a package's import path in its
   184  own source code, making it easier to move the code from one location to another.
   185  </p>
   186  
   187  <h3 id="directives">Directives</h3>
   188  
   189  <p>
   190  The assembler uses various directives to bind text and data to symbol names.
   191  For example, here is a simple complete function definition. The <code>TEXT</code>
   192  directive declares the symbol <code>runtime·profileloop</code> and the instructions
   193  that follow form the body of the function.
   194  The last instruction in a <code>TEXT</code> block must be some sort of jump, usually a <code>RET</code> (pseudo-)instruction.
   195  (If it's not, the linker will append a jump-to-itself instruction; there is no fallthrough in <code>TEXTs</code>.)
   196  After the symbol, the arguments are flags (see below)
   197  and the frame size, a constant (but see below):
   198  </p>
   199  
   200  <pre>
   201  TEXT runtime·profileloop(SB),NOSPLIT,$8
   202  	MOVQ	$runtime·profileloop1(SB), CX
   203  	MOVQ	CX, 0(SP)
   204  	CALL	runtime·externalthreadhandler(SB)
   205  	RET
   206  </pre>
   207  
   208  <p>
   209  In the general case, the frame size is followed by an argument size, separated by a minus sign.
   210  (It's not a subtraction, just idiosyncratic syntax.)
   211  The frame size <code>$24-8</code> states that the function has a 24-byte frame
   212  and is called with 8 bytes of argument, which live on the caller's frame.
   213  If <code>NOSPLIT</code> is not specified for the <code>TEXT</code>,
   214  the argument size must be provided.
   215  For assembly functions with Go prototypes, <code>go</code> <code>vet</code> will check that the
   216  argument size is correct.
   217  </p>
   218  
   219  <p>
   220  Note that the symbol name uses a middle dot to separate the components and is specified as an offset from the
   221  static base pseudo-register <code>SB</code>.
   222  This function would be called from Go source for package <code>runtime</code> using the
   223  simple name <code>profileloop</code>.
   224  </p>
   225  
   226  <p>
   227  Global data symbols are defined by a sequence of initializing
   228  <code>DATA</code> directives followed by a <code>GLOBL</code> directive.
   229  Each <code>DATA</code> directive initializes a section of the
   230  corresponding memory.
   231  The memory not explicitly initialized is zeroed.
   232  The general form of the <code>DATA</code> directive is
   233  
   234  <pre>
   235  DATA	symbol+offset(SB)/width, value
   236  </pre>
   237  
   238  <p>
   239  which initializes the symbol memory at the given offset and width with the given value.
   240  The <code>DATA</code> directives for a given symbol must be written with increasing offsets.
   241  </p>
   242  
   243  <p>
   244  The <code>GLOBL</code> directive declares a symbol to be global.
   245  The arguments are optional flags and the size of the data being declared as a global,
   246  which will have initial value all zeros unless a <code>DATA</code> directive
   247  has initialized it.
   248  The <code>GLOBL</code> directive must follow any corresponding <code>DATA</code> directives.
   249  </p>
   250  
   251  <p>
   252  For example,
   253  </p>
   254  
   255  <pre>
   256  DATA divtab&lt;&gt;+0x00(SB)/4, $0xf4f8fcff
   257  DATA divtab&lt;&gt;+0x04(SB)/4, $0xe6eaedf0
   258  ...
   259  DATA divtab&lt;&gt;+0x3c(SB)/4, $0x81828384
   260  GLOBL divtab&lt;&gt;(SB), RODATA, $64
   261  
   262  GLOBL runtime·tlsoffset(SB), NOPTR, $4
   263  </pre>
   264  
   265  <p>
   266  declares and initializes <code>divtab&lt;&gt;</code>, a read-only 64-byte table of 4-byte integer values,
   267  and declares <code>runtime·tlsoffset</code>, a 4-byte, implicitly zeroed variable that
   268  contains no pointers.
   269  </p>
   270  
   271  <p>
   272  There may be one or two arguments to the directives.
   273  If there are two, the first is a bit mask of flags,
   274  which can be written as numeric expressions, added or or-ed together,
   275  or can be set symbolically for easier absorption by a human.
   276  Their values, defined in the standard <code>#include</code>  file <code>textflag.h</code>, are:
   277  </p>
   278  
   279  <ul>
   280  <li>
   281  <code>NOPROF</code> = 1
   282  <br>
   283  (For <code>TEXT</code> items.)
   284  Don't profile the marked function.  This flag is deprecated.
   285  </li>
   286  <li>
   287  <code>DUPOK</code> = 2
   288  <br>
   289  It is legal to have multiple instances of this symbol in a single binary.
   290  The linker will choose one of the duplicates to use.
   291  </li>
   292  <li>
   293  <code>NOSPLIT</code> = 4
   294  <br>
   295  (For <code>TEXT</code> items.)
   296  Don't insert the preamble to check if the stack must be split.
   297  The frame for the routine, plus anything it calls, must fit in the
   298  spare space at the top of the stack segment.
   299  Used to protect routines such as the stack splitting code itself.
   300  </li>
   301  <li>
   302  <code>RODATA</code> = 8
   303  <br>
   304  (For <code>DATA</code> and <code>GLOBL</code> items.)
   305  Put this data in a read-only section.
   306  </li>
   307  <li>
   308  <code>NOPTR</code> = 16
   309  <br>
   310  (For <code>DATA</code> and <code>GLOBL</code> items.)
   311  This data contains no pointers and therefore does not need to be
   312  scanned by the garbage collector.
   313  </li>
   314  <li>
   315  <code>WRAPPER</code>  = 32
   316  <br>
   317  (For <code>TEXT</code> items.)
   318  This is a wrapper function and should not count as disabling <code>recover</code>.
   319  </li>
   320  </ul>
   321  
   322  <h3 id="runtime">Runtime Coordination</h3>
   323  
   324  <p>
   325  For garbage collection to run correctly, the runtime must know the
   326  location of pointers in all global data and in most stack frames.
   327  The Go compiler emits this information when compiling Go source files,
   328  but assembly programs must define it explicitly.
   329  </p>
   330  
   331  <p>
   332  A data symbol marked with the <code>NOPTR</code> flag (see above)
   333  is treated as containing no pointers to runtime-allocated data.
   334  A data symbol with the <code>RODATA</code> flag
   335  is allocated in read-only memory and is therefore treated
   336  as implicitly marked <code>NOPTR</code>.
   337  A data symbol with a total size smaller than a pointer
   338  is also treated as implicitly marked <code>NOPTR</code>.
   339  It is not possible to define a symbol containing pointers in an assembly source file;
   340  such a symbol must be defined in a Go source file instead.
   341  Assembly source can still refer to the symbol by name
   342  even without <code>DATA</code> and <code>GLOBL</code> directives.
   343  A good general rule of thumb is to define all non-<code>RODATA</code>
   344  symbols in Go instead of in assembly.
   345  </p>
   346  
   347  <p>
   348  Each function also needs annotations giving the location of
   349  live pointers in its arguments, results, and local stack frame.
   350  For an assembly function with no pointer results and
   351  either no local stack frame or no function calls,
   352  the only requirement is to define a Go prototype for the function
   353  in a Go source file in the same package. The name of the assembly
   354  function must not contain the package name component (for example,
   355  function <code>Syscall</code> in package <code>syscall</code> should
   356  use the name <code>·Syscall</code> instead of the equivalent name
   357  <code>syscall·Syscall</code> in its <code>TEXT</code> directive).
   358  For more complex situations, explicit annotation is needed.
   359  These annotations use pseudo-instructions defined in the standard
   360  <code>#include</code> file <code>funcdata.h</code>.
   361  </p>
   362  
   363  <p>
   364  If a function has no arguments and no results,
   365  the pointer information can be omitted.
   366  This is indicated by an argument size annotation of <code>$<i>n</i>-0</code>
   367  on the <code>TEXT</code> instruction.
   368  Otherwise, pointer information must be provided by
   369  a Go prototype for the function in a Go source file,
   370  even for assembly functions not called directly from Go.
   371  (The prototype will also let <code>go</code> <code>vet</code> check the argument references.)
   372  At the start of the function, the arguments are assumed
   373  to be initialized but the results are assumed uninitialized.
   374  If the results will hold live pointers during a call instruction,
   375  the function should start by zeroing the results and then 
   376  executing the pseudo-instruction <code>GO_RESULTS_INITIALIZED</code>.
   377  This instruction records that the results are now initialized
   378  and should be scanned during stack movement and garbage collection.
   379  It is typically easier to arrange that assembly functions do not
   380  return pointers or do not contain call instructions;
   381  no assembly functions in the standard library use
   382  <code>GO_RESULTS_INITIALIZED</code>.
   383  </p>
   384  
   385  <p>
   386  If a function has no local stack frame,
   387  the pointer information can be omitted.
   388  This is indicated by a local frame size annotation of <code>$0-<i>n</i></code>
   389  on the <code>TEXT</code> instruction.
   390  The pointer information can also be omitted if the
   391  function contains no call instructions.
   392  Otherwise, the local stack frame must not contain pointers,
   393  and the assembly must confirm this fact by executing the 
   394  pseudo-instruction <code>NO_LOCAL_POINTERS</code>.
   395  Because stack resizing is implemented by moving the stack,
   396  the stack pointer may change during any function call:
   397  even pointers to stack data must not be kept in local variables.
   398  </p>
   399  
   400  <h2 id="architectures">Architecture-specific details</h2>
   401  
   402  <p>
   403  It is impractical to list all the instructions and other details for each machine.
   404  To see what instructions are defined for a given machine, say 32-bit Intel x86,
   405  look in the top-level header file for the corresponding linker, in this case <code>8l</code>.
   406  That is, the file <code>$GOROOT/src/cmd/8l/8.out.h</code> contains a C enumeration, called <code>as</code>,
   407  of the instructions and their spellings as known to the assembler and linker for that architecture.
   408  In that file you'll find a declaration that begins
   409  </p>
   410  
   411  <pre>
   412  enum	as
   413  {
   414  	AXXX,
   415  	AAAA,
   416  	AAAD,
   417  	AAAM,
   418  	AAAS,
   419  	AADCB,
   420  	...
   421  </pre>
   422  
   423  <p>
   424  Each instruction begins with a  initial capital <code>A</code> in this list, so <code>AADCB</code>
   425  represents the <code>ADCB</code> (add carry byte) instruction.
   426  The enumeration is in alphabetical order, plus some late additions (<code>AXXX</code> occupies
   427  the zero slot as an invalid instruction).
   428  The sequence has nothing to do with the actual encoding of the machine instructions.
   429  Again, the linker takes care of that detail.
   430  </p>
   431  
   432  <p>
   433  One detail evident in the examples from the previous sections is that data in the instructions flows from left to right:
   434  <code>MOVQ</code> <code>$0,</code> <code>CX</code> clears <code>CX</code>.
   435  This convention applies even on architectures where the usual mode is the opposite direction.
   436  </p>
   437  
   438  <p>
   439  Here follows some descriptions of key Go-specific details for the supported architectures.
   440  </p>
   441  
   442  <h3 id="x86">32-bit Intel 386</h3>
   443  
   444  <p>
   445  The runtime pointer to the <code>g</code> structure is maintained
   446  through the value of an otherwise unused (as far as Go is concerned) register in the MMU.
   447  A OS-dependent macro <code>get_tls</code> is defined for the assembler if the source includes
   448  an architecture-dependent header file, like this:
   449  </p>
   450  
   451  <pre>
   452  #include "zasm_GOOS_GOARCH.h"
   453  </pre>
   454  
   455  <p>
   456  Within the runtime, the <code>get_tls</code> macro loads its argument register
   457  with a pointer to the <code>g</code> pointer, and the <code>g</code> struct
   458  contains the <code>m</code> pointer.
   459  The sequence to load <code>g</code> and <code>m</code> using <code>CX</code> looks like this:
   460  </p>
   461  
   462  <pre>
   463  get_tls(CX)
   464  MOVL	g(CX), AX     // Move g into AX.
   465  MOVL	g_m(AX), BX   // Move g->m into BX.
   466  </pre>
   467  
   468  <h3 id="amd64">64-bit Intel 386 (a.k.a. amd64)</h3>
   469  
   470  <p>
   471  The assembly code to access the <code>m</code> and <code>g</code>
   472  pointers is the same as on the 386, except it uses <code>MOVQ</code> rather than
   473  <code>MOVL</code>:
   474  </p>
   475  
   476  <pre>
   477  get_tls(CX)
   478  MOVQ	g(CX), AX     // Move g into AX.
   479  MOVQ	g_m(AX), BX   // Move g->m into BX.
   480  </pre>
   481  
   482  <h3 id="arm">ARM</h3>
   483  
   484  <p>
   485  The registers <code>R10</code> and <code>R11</code>
   486  are reserved by the compiler and linker.
   487  </p>
   488  
   489  <p>
   490  <code>R10</code> points to the <code>g</code> (goroutine) structure.
   491  Within assembler source code, this pointer must be referred to as <code>g</code>;
   492  the name <code>R10</code> is not recognized.
   493  </p>
   494  
   495  <p>
   496  To make it easier for people and compilers to write assembly, the ARM linker
   497  allows general addressing forms and pseudo-operations like <code>DIV</code> or <code>MOD</code>
   498  that may not be expressible using a single hardware instruction.
   499  It implements these forms as multiple instructions, often using the <code>R11</code> register
   500  to hold temporary values.
   501  Hand-written assembly can use <code>R11</code>, but doing so requires
   502  being sure that the linker is not also using it to implement any of the other
   503  instructions in the function.
   504  </p>
   505  
   506  <p>
   507  When defining a <code>TEXT</code>, specifying frame size <code>$-4</code>
   508  tells the linker that this is a leaf function that does not need to save <code>LR</code> on entry.
   509  </p>
   510  
   511  <p>
   512  The name <code>SP</code> always refers to the virtual stack pointer described earlier.
   513  For the hardware register, use <code>R13</code>.
   514  </p>
   515  
   516  <h3 id="unsupported_opcodes">Unsupported opcodes</h3>
   517  
   518  <p>
   519  The assemblers are designed to support the compiler so not all hardware instructions
   520  are defined for all architectures: if the compiler doesn't generate it, it might not be there.
   521  If you need to use a missing instruction, there are two ways to proceed.
   522  One is to update the assembler to support that instruction, which is straightforward
   523  but only worthwhile if it's likely the instruction will be used again.
   524  Instead, for simple one-off cases, it's possible to use the <code>BYTE</code>
   525  and <code>WORD</code> directives
   526  to lay down explicit data into the instruction stream within a <code>TEXT</code>.
   527  Here's how the 386 runtime defines the 64-bit atomic load function.
   528  </p>
   529  
   530  <pre>
   531  // uint64 atomicload64(uint64 volatile* addr);
   532  // so actually
   533  // void atomicload64(uint64 *res, uint64 volatile *addr);
   534  TEXT runtime·atomicload64(SB), NOSPLIT, $0-8
   535  	MOVL	ptr+0(FP), AX
   536  	LEAL	ret_lo+4(FP), BX
   537  	BYTE $0x0f; BYTE $0x6f; BYTE $0x00	// MOVQ (%EAX), %MM0
   538  	BYTE $0x0f; BYTE $0x7f; BYTE $0x03	// MOVQ %MM0, 0(%EBX)
   539  	BYTE $0x0F; BYTE $0x77			// EMMS
   540  	RET
   541  </pre>