docs(asm): open the assembly language reference
Assisted-by: GLM 5.3 Flash
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# Preprocessing: include, define and selection
|
||||
|
||||
Layer 1, the common language. Verified against the preprocessor inside
|
||||
`go tool asm` of Go 1.27.1 (`cmd/asm/internal/lex`), whose directives are
|
||||
`#define`, `#undef`, `#include`, `#ifdef`, `#ifndef`, `#else`, `#endif` and
|
||||
`#line`, and against gasm's implementation, which is differentially tested
|
||||
against the toolchain's.
|
||||
|
||||
Input runs through a simplified C preprocessor before the parser sees it.
|
||||
The set is deliberately small: there is no `#if` with constant expressions
|
||||
and no token pasting with `##`. `#line` is honoured, so it changes the
|
||||
positions the assembler reports and records.
|
||||
|
||||
## #include
|
||||
|
||||
```text
|
||||
#include "textflag.h"
|
||||
#include "go_asm.h"
|
||||
#include "defs_linux_amd64.h"
|
||||
```
|
||||
|
||||
The search path, in order: the directory of the including file, then the
|
||||
directories given by repeatable `-I` flags. The assembler seeds no default
|
||||
of its own: a bare `go tool asm` invocation finds none of the standard
|
||||
headers, and it is the `go` build system that passes `$GOROOT/pkg/include`
|
||||
among the `-I` directories when it drives the build. That directory ships
|
||||
`textflag.h`, `funcdata.h` and the per architecture register headers.
|
||||
Includes nest; a file included twice through different paths is processed
|
||||
twice, which is why headers guard their defines.
|
||||
|
||||
## #define and #undef
|
||||
|
||||
```text
|
||||
#define bufSize 1024
|
||||
#define MOVD(d, s) MOVQ s, d
|
||||
#undef bufSize
|
||||
```
|
||||
|
||||
- An object macro replaces its name with its token sequence at the point of
|
||||
use.
|
||||
- A parameterised macro takes its arguments in parentheses and substitutes
|
||||
them into the body. Macro parameters compose with the rest of the
|
||||
language: an argument used with an element suffix, as in `A.S4` on the
|
||||
vector forms, substitutes correctly.
|
||||
- Redefinition is an error; `#undef` first, or pick a new name.
|
||||
- The `-D name[=value]` flag predefines an object macro from the command
|
||||
line, repeatable, exactly as `#define` would; a `-D` without a value
|
||||
defines the name as `1`.
|
||||
- Expansion happens when the name is used, so a macro may expand to
|
||||
instructions, operands or fragments of either, and a macro body may use
|
||||
macros defined before it.
|
||||
|
||||
`textflag.h` and `funcdata.h` are themselves ordinary `#define` files: the
|
||||
flag names and the runtime macros are preprocessor definitions, not language
|
||||
keywords. That is why a missing include produces a parser error at the first
|
||||
use of `NOSPLIT` rather than a complaint about the name.
|
||||
|
||||
## #ifdef, #ifndef, #else, #endif
|
||||
|
||||
```text
|
||||
#ifdef GOOS_windows
|
||||
#define SYSCALL_INT 0x2b
|
||||
#endif
|
||||
```
|
||||
|
||||
Selection is by defined-name only: `#ifdef`, `#ifndef`, `#else`, `#endif`,
|
||||
nesting freely. There is no `#if defined(x) && y`, because the preprocessor
|
||||
evaluates no expressions; reach that with a build-tag Go file generating a
|
||||
header, which is exactly how the runtime's own `go_asm.h` and defs headers
|
||||
are produced.
|
||||
|
||||
## What preprocessing does not cover
|
||||
|
||||
The preprocessor is textual and runs first, so it knows nothing of assembly
|
||||
semantics: it does not check that a macro expansion is a legal instruction,
|
||||
and it does not participate in the constant expression evaluator, which runs
|
||||
later, in the parser. A constant folded with `#define` and a constant folded
|
||||
in an operand expression end at the same value through different doors;
|
||||
GOOBJ.md records both in the object identically.
|
||||
Reference in New Issue
Block a user