]> Cypherpunks.ru repositories - gostls13.git/blob - doc/asm.html
doc/asm: more about SP, ARM R11
[gostls13.git] / doc / asm.html
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>