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