[インデックス 17886] ファイルの概要
このコミットは、Go言語のアセンブラに関する公式ドキュメント(doc/asm.html
)の記述を改善し、特に仮想スタックポインタ(SP
)とARMアーキテクチャにおけるレジスタR11
の利用に関する説明を詳細化したものです。また、ドキュメントのURLパスをより簡潔な形式に変更しています。
コミット
doc/asm: more about SP, ARM R11
Also rename URL to /doc/asm.
R=golang-dev, minux.ma, r
CC=golang-dev
https://golang.org/cl/26170043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/a664b4945703f2b92a81e4aafc8c6dcaa796296d
元コミット内容
commit a664b4945703f2b92a81e4aafc8c6dcaa796296d
Author: Russ Cox <rsc@golang.org>
Date: Wed Nov 13 21:29:34 2013 -0500
doc/asm: more about SP, ARM R11
Also rename URL to /doc/asm.
R=golang-dev, minux.ma, r
CC=golang-dev
https://golang.org/cl/26170043
---
doc/asm.html | 53 +++++++++++++++++++++++++++++++++++++++++++++--------
src/cmd/5a/doc.go | 2 +-\
src/cmd/6a/doc.go | 4 ++--
src/cmd/8a/doc.go | 2 +-\
4 files changed, 49 insertions(+), 12 deletions(-)
diff --git a/doc/asm.html b/doc/asm.html
index ba19700643..b855b9ef7a 100644
--- a/doc/asm.html
+++ b/doc/asm.html
@@ -1,6 +1,6 @@
<!--{
"Title": "A Quick Guide to Go's Assembler",
-"Path": "/doc/asm.html"\n+\t"Path": "/doc/asm"\n }-->
\n <h2 id="introduction">A Quick Guide to Go's Assembler</h2>
@@ -113,12 +113,30 @@ is the name <code>foo</code> as an address in memory.\n </p>\n \n <p>\n-The <code>FP</code> is a virtual frame pointer.\n+The <code>FP</code> pseudo-register is a virtual frame pointer\n+used to refer to function arguments.\n The compilers maintain a virtual frame pointer and refer to the arguments on the stack as offsets from that pseudo-register.\n Thus <code>0(FP)</code> is the first argument to the function,\n <code>8(FP)</code> is the second (on a 64-bit machine), and so on.\n-To refer to an argument by name, add the name to the numerical offset, like this: <code>first_arg+0(FP)</code>.\n-The name in this syntax has no semantic value; think of it as a comment to the reader.\n+When referring to a function argument this way, it is conventional to place the name\n+at the beginning, as in <code>first_arg+0(FP)</code> and <code>second_arg+8(FP)</code>.\n+Some of the assemblers enforce this convention, rejecting plain <code>0(FP)</code> and <code>8(FP)</code>.\n+For assembly functions with Go prototypes, <code>go vet</code> will check that the argument names\n+and offsets match.\n+</p>\n+\n+<p>\n+The <code>SP</code> pseudo-register is a virtual stack pointer\n+used to refer to frame-local variables and the arguments being\n+prepared for function calls.\n+It points to the top of the local stack frame, so references should use negative offsets\n+in the range [−framesize, 0):\n+<code>x-8(SP)</code>, <code>y-4(SP)</code>, and so on.\n+On architectures with a real register named <code>SP</code>, the name prefix distinguishes\n+references to the virtual stack pointer from references to the architectural <code>SP</code> register.\n+That is, <code>x-8(SP)</code> and <code>-8(SP)</code> are different memory locations:\n+the first refers to the virtual stack pointer pseudo-register, while the second refers to the\n+hardware's <code>SP</code> register.\n </p>\n \n <p>\n@@ -358,11 +376,26 @@ MOVQ\tm(CX), BX\t// Move m into BX.\n <h3 id=\"arm\">ARM</h3>\n \n <p>\n-The registers <code>R9</code> and <code>R10</code> are reserved by the\n-compiler and linker to point to the <code>m</code> (machine) and <code>g</code>\n+The registers <code>R9</code>, <code>R10</code>, and <code>R11</code>\n+are reserved by the compiler and linker.\n+</p>\n+\n+<p>\n+<code>R9</code> and <code>R10</code> point to the <code>m</code> (machine) and <code>g</code>\n (goroutine) structures, respectively.\n-Within assembler source code, these pointers\n-can be referred to as simply <code>m</code> and <code>g</code>. \n+Within assembler source code, these pointers must be referred to as <code>m</code> and <code>g</code>;\n+the names <code>R9</code> and <code>R10</code> are not recognized.\n+</p>\n+\n+<p>\n+To make it easier for people and compilers to write assembly, the ARM linker\n+allows general addressing forms and pseudo-operations like <code>DIV</code> or <code>MOD</code>\n+that may not be expressible using a single hardware instruction.\n+It implements these forms as multiple instructions, often using the <code>R11</code> register\n+to hold temporary values.\n+Hand-written assembly can use <code>R11</code>, but doing so requires\n+being sure that the linker is not also using it to implement any of the other\n+instructions in the function.\n </p>\n \n <p>\n@@ -370,6 +403,10 @@ When defining a <code>TEXT</code>, specifying frame size <code>$-4</code>\n tells the linker that this is a leaf function that does not need to save <code>LR</code> on entry.\n </p>\n \n+<p>\n+The name <code>SP</code> always refers to the virtual stack pointer described earlier.\n+For the hardware register, use <code>R13</code>.\n+</p>\n \n <h3 id=\"unsupported_opcodes\">Unsupported opcodes</h3>\n \ndiff --git a/src/cmd/5a/doc.go b/src/cmd/5a/doc.go\nindex 74d025fe2c..3e9e78fe6d 100644\n--- a/src/cmd/5a/doc.go\n+++ b/src/cmd/5a/doc.go\n@@ -12,7 +12,7 @@\n \n Go-specific considerations are documented at\n \n-\thttp://golang.org/doc/asm.html\n+\thttp://golang.org/doc/asm\n \n Its target architecture is the ARM, referred to by these tools as arm.\n \ndiff --git a/src/cmd/6a/doc.go b/src/cmd/6a/doc.go\nindex 9fdc6ed3a5..9f14cc0d05 100644\n--- a/src/cmd/6a/doc.go\n+++ b/src/cmd/6a/doc.go\n@@ -12,9 +12,9 @@\n \n Go-specific considerations are documented at\n \n-\thttp://golang.org/doc/asm.html\n+\thttp://golang.org/doc/asm\n \n-IIts target architecture is the x86-64, referred to by these tools as amd64.\n+Its target architecture is the x86-64, referred to by these tools as amd64.\n \n */\n package main\ndiff --git a/src/cmd/8a/doc.go b/src/cmd/8a/doc.go\nindex bdf2fcfbb7..84c7254c80 100644\n--- a/src/cmd/8a/doc.go\n+++ b/src/cmd/8a/doc.go\n@@ -12,7 +12,7 @@\n \n Go-specific considerations are documented at\n \n-\thttp://golang.org/doc/asm.html\n+\thttp://golang.org/doc/asm\n \n I\n Its target architecture is the x86, referred to by these tools for historical reasons as 386.\n```
## 変更の背景
このコミットの主な背景は、Go言語のアセンブラを使用する開発者にとって、より明確で正確なドキュメントを提供することにあります。特に、スタック操作に関連する仮想レジスタ(`SP`)の挙動と、ARMアーキテクチャにおける特定のレジスタ(`R11`)の予約と使用に関する情報が不足していたため、これらの詳細を追加することで、アセンブラコードの記述や理解を容易にすることが目的です。
また、ドキュメントのURLパスを簡潔なものに変更することで、よりアクセスしやすく、一般的なドキュメント構造に合わせる意図もあります。これは、Goプロジェクト全体のドキュメント管理の一環として行われた可能性があります。
## 前提知識の解説
このコミットの変更内容を理解するためには、以下の前提知識が必要です。
* **Go言語のアセンブラ**: Go言語は、特定のパフォーマンスが要求される場面や、OSとの低レベルなインタラクションが必要な場合に、Goのアセンブラ(Plan 9アセンブラをベースとする)を使用してアセンブリコードを記述する機能を提供します。これは、C言語におけるインラインアセンブラとは異なり、独立したアセンブリファイルとして記述されます。
* **仮想レジスタ(Pseudo-Registers)**: Goのアセンブラには、実際のハードウェアレジスタとは異なる「仮想レジスタ」という概念があります。これらはコンパイラやリンカが内部的に管理し、アセンブラコードの記述を抽象化・簡略化するために使用されます。
* **`FP` (Frame Pointer)**: 関数引数を参照するための仮想フレームポインタです。スタック上の引数にアクセスする際に、`0(FP)`、`8(FP)`のようにオフセットを指定して使用します。慣例として、`first_arg+0(FP)`のように引数名を付加します。
* **`SP` (Stack Pointer)**: フレームローカル変数や関数呼び出しのために準備される引数を参照するための仮想スタックポインタです。ローカルスタックフレームの先頭を指し、`x-8(SP)`のように負のオフセットを使用してアクセスします。
* **ARMアーキテクチャ**: ARMは、モバイルデバイスなどで広く使用されているRISC(Reduced Instruction Set Computer)ベースのプロセッサアーキテクチャです。ARMプロセッサには、汎用レジスタ(R0-R15など)があり、それぞれ特定の用途や慣例があります。
* **`R9`, `R10`**: Goのランタイムにおいて、`m`(machine、OSスレッドのコンテキスト)と`g`(goroutine、Goの軽量スレッド)構造体へのポインタとして予約されています。アセンブラコード内では、これらのレジスタは`m`と`g`という名前で参照されます。
* **`R11`**: このコミットで説明が追加されたレジスタです。ARMリンカが、単一のハードウェア命令では表現できないような汎用アドレッシング形式や擬似操作(例: `DIV`, `MOD`)を実装する際に、一時的な値を保持するために使用することがあります。
* **`R13`**: ARMアーキテクチャにおけるハードウェアのスタックポインタ(SP)レジスタです。Goのアセンブラにおける仮想`SP`と区別するために、ハードウェアのSPを参照する際には`R13`を使用します。
* **`go vet`**: Goのコードを静的に解析し、潜在的なバグや疑わしい構造を検出するツールです。アセンブリ関数がGoのプロトタイプを持つ場合、`go vet`は引数名とオフセットが一致するかどうかをチェックします。
* **リンカの役割**: リンカは、コンパイルされたオブジェクトファイルやライブラリを結合して実行可能ファイルを生成するツールです。アセンブリコードにおいては、リンカが特定の擬似命令を複数のハードウェア命令に展開したり、レジスタの使用を調整したりすることがあります。
## 技術的詳細
このコミットは、主に`doc/asm.html`ファイルの更新を通じて、Goのアセンブラに関するドキュメントの精度と詳細度を向上させています。
1. **`SP` (Stack Pointer) の詳細化**:
* 以前は`FP`(フレームポインタ)の説明に比べて`SP`に関する記述が不足していました。
* 今回の変更で、`SP`が仮想スタックポインタであり、フレームローカル変数や関数呼び出しの引数を参照するために使用されることが明確にされました。
* `SP`がローカルスタックフレームのトップを指すため、参照には`x-8(SP)`のように負のオフセットを使用することが強調されています。
* 最も重要な追加は、実際のハードウェアレジスタに`SP`という名前が存在するアーキテクチャ(例: ARMの`R13`)において、仮想`SP`とハードウェア`SP`を区別する方法が明記された点です。`x-8(SP)`は仮想スタックポインタを参照するのに対し、`-8(SP)`はハードウェアの`SP`レジスタを参照するという違いが明確に説明されています。
2. **ARM `R11` レジスタに関する追加情報**:
* 以前のドキュメントでは、ARMの`R9`と`R10`が`m`と`g`構造体へのポインタとして予約されていることのみが言及されていました。
* 今回の変更で、`R11`もコンパイラとリンカによって予約されているレジスタであることが追加されました。
* ARMリンカが、`DIV`や`MOD`のような単一命令で表現できない擬似操作を実装する際に、一時的な値を保持するために`R11`を使用する可能性があることが説明されています。
* 手書きのアセンブリコードで`R11`を使用することは可能ですが、その場合、リンカが同じ関数内の他の命令を実装するために`R11`を使用していないことを確認する必要があるという重要な注意点が追加されました。これは、リンカによるレジスタの暗黙的な使用が、手書きコードの意図しない動作を引き起こす可能性があるためです。
* また、ARMアーキテクチャにおいて、仮想`SP`は常に`SP`という名前で参照され、ハードウェアのスタックポインタは`R13`として参照されることが明記されました。
3. **ドキュメントURLパスの変更**:
* `doc/asm.html`のメタデータ内の`Path`が`/doc/asm.html`から`/doc/asm`に変更されました。
* これに伴い、`src/cmd/5a/doc.go`、`src/cmd/6a/doc.go`、`src/cmd/8a/doc.go`といった各アーキテクチャのアセンブラツールのドキュメントファイル内で参照されているURLも、新しいパスに更新されています。これは、GoのドキュメントサイトにおけるURLの正規化と簡潔化の一環と考えられます。
これらの変更は、Goのアセンブラを扱う開発者が直面する可能性のある混乱を解消し、より正確で完全な情報を提供することを目的としています。特に、仮想レジスタと物理レジスタの区別、およびリンカによるレジスタの暗黙的な使用に関する注意点は、低レベルプログラミングにおける重要な側面です。
## コアとなるコードの変更箇所
このコミットによる主要なコード変更は、以下のファイルに集中しています。
1. **`doc/asm.html`**:
* `FP`の説明が拡張され、`go vet`による引数名とオフセットのチェックに関する記述が追加されました。
* `SP`に関する新しい段落が追加され、仮想スタックポインタとしての役割、負のオフセットの使用、およびハードウェア`SP`との区別(`x-8(SP)` vs `-8(SP)`)が詳細に説明されました。
* ARMセクションにおいて、`R11`が予約レジスタに追加され、リンカが一時値のために`R11`を使用する可能性と、手書きアセンブリで`R11`を使用する際の注意点が追記されました。
* ARMセクションの最後に、仮想`SP`とハードウェア`R13`(実際のSPレジスタ)の区別に関する記述が追加されました。
* ファイルの冒頭にあるメタデータで、`"Path": "/doc/asm.html"` が `"Path": "/doc/asm"` に変更されました。
2. **`src/cmd/5a/doc.go`**:
* 参照しているドキュメントURLが `http://golang.org/doc/asm.html` から `http://golang.org/doc/asm` に変更されました。
3. **`src/cmd/6a/doc.go`**:
* 参照しているドキュメントURLが `http://golang.org/doc/asm.html` から `http://golang.org/doc/asm` に変更されました。
* タイプミス `IIts` が `Its` に修正されました。
4. **`src/cmd/8a/doc.go`**:
* 参照しているドキュメントURLが `http://golang.org/doc/asm.html` から `http://golang.org/doc/asm` に変更されました。
## コアとなるコードの解説
### `doc/asm.html` の変更点
* **`FP`と`SP`の明確化**:
```diff
--- a/doc/asm.html
+++ b/doc/asm.html
@@ -113,12 +113,30 @@ is the name <code>foo</code> as an address in memory.\n </p>\n \n <p>\n-The <code>FP</code> is a virtual frame pointer.\n+The <code>FP</code> pseudo-register is a virtual frame pointer\n+used to refer to function arguments.\n The compilers maintain a virtual frame pointer and refer to the arguments on the stack as offsets from that pseudo-register.\n Thus <code>0(FP)</code> is the first argument to the function,\n <code>8(FP)</code> is the second (on a 64-bit machine), and so on.\n-To refer to an argument by name, add the name to the numerical offset, like this: <code>first_arg+0(FP)</code>.\n-The name in this syntax has no semantic value; think of it as a comment to the reader.\n+When referring to a function argument this way, it is conventional to place the name\n+at the beginning, as in <code>first_arg+0(FP)</code> and <code>second_arg+8(FP)</code>.\n+Some of the assemblers enforce this convention, rejecting plain <code>0(FP)</code> and <code>8(FP)</code>.\n+For assembly functions with Go prototypes, <code>go vet</code> will check that the argument names\n+and offsets match.\n+</p>\n+\n+<p>\n+The <code>SP</code> pseudo-register is a virtual stack pointer\n+used to refer to frame-local variables and the arguments being\n+prepared for function calls.\n+It points to the top of the local stack frame, so references should use negative offsets\n+in the range [−framesize, 0):\n+<code>x-8(SP)</code>, <code>y-4(SP)</code>, and so on.\n+On architectures with a real register named <code>SP</code>, the name prefix distinguishes\n+references to the virtual stack pointer from references to the architectural <code>SP</code> register.\n+That is, <code>x-8(SP)</code> and <code>-8(SP)</code> are different memory locations:\n+the first refers to the virtual stack pointer pseudo-register, while the second refers to the\n+hardware's <code>SP</code> register.\n </p>\n ```
この変更は、`FP`と`SP`というGoアセンブラの仮想レジスタに関する理解を深めるものです。特に`SP`については、ローカル変数や関数呼び出しの引数へのアクセス方法(負のオフセット)と、ハードウェアの`SP`レジスタとの混同を避けるための明確な区別(`x-8(SP)`と`-8(SP)`の違い)が追加されました。これにより、アセンブラコードのデバッグや移植性が向上します。`go vet`によるチェックの言及は、Goのツールチェーンがアセンブリコードの正確性をどのように支援しているかを示しています。
* **ARM `R11`と`R13`の追加説明**:
```diff
--- a/doc/asm.html
+++ b/doc/asm.html
@@ -358,11 +376,26 @@ MOVQ\tm(CX), BX\t// Move m into BX.\n <h3 id="arm">ARM</h3>\n \n <p>\n-The registers <code>R9</code> and <code>R10</code> are reserved by the\n-compiler and linker to point to the <code>m</code> (machine) and <code>g</code>\n+The registers <code>R9</code>, <code>R10</code>, and <code>R11</code>\n+are reserved by the compiler and linker.\n+</p>\n+\n+<p>\n+<code>R9</code> and <code>R10</code> point to the <code>m</code> (machine) and <code>g</code>\n (goroutine) structures, respectively.\n-Within assembler source code, these pointers\n-can be referred to as simply <code>m</code> and <code>g</code>. \n+Within assembler source code, these pointers must be referred to as <code>m</code> and <code>g</code>;\n+the names <code>R9</code> and <code>R10</code> are not recognized.\n+</p>\n+\n+<p>\n+To make it easier for people and compilers to write assembly, the ARM linker\n+allows general addressing forms and pseudo-operations like <code>DIV</code> or <code>MOD</code>\n+that may not be expressible using a single hardware instruction.\n+It implements these forms as multiple instructions, often using the <code>R11</code> register\n+to hold temporary values.\n+Hand-written assembly can use <code>R11</code>, but doing so requires\n+being sure that the linker is not also using it to implement any of the other\n+instructions in the function.\n </p>\n \n <p>\n@@ -370,6 +403,10 @@ When defining a <code>TEXT</code>, specifying frame size <code>$-4</code>\n tells the linker that this is a leaf function that does not need to save <code>LR</code> on entry.\n </p>\n \n+<p>\n+The name <code>SP</code> always refers to the virtual stack pointer described earlier.\n+For the hardware register, use <code>R13</code>.\n+</p>\n ```
このセクションでは、ARMアーキテクチャにおけるレジスタの予約と使用に関する重要な情報が追加されました。特に`R11`がリンカによって一時的な値のために使用される可能性があるという警告は、手書きアセンブリコードの潜在的なバグを防ぐ上で非常に重要です。また、ARMのハードウェアSPが`R13`として参照されることの明記は、クロスアーキテクチャ開発における混乱を避けるのに役立ちます。
* **URLパスの変更**:
```diff
--- a/doc/asm.html
+++ b/doc/asm.html
@@ -1,6 +1,6 @@
<!--{
"Title": "A Quick Guide to Go's Assembler",
-"Path": "/doc/asm.html"\n+\t"Path": "/doc/asm"\n }-->
```
これはドキュメント自体のメタデータ変更であり、GoのドキュメントサイトにおけるURLの正規化と簡潔化を反映しています。
### `src/cmd/*/doc.go` ファイルの変更点
* **URL参照の更新**:
```diff
--- a/src/cmd/5a/doc.go
+++ b/src/cmd/5a/doc.go
@@ -12,7 +12,7 @@
Go-specific considerations are documented at
-\thttp://golang.org/doc/asm.html\n+\thttp://golang.org/doc/asm\n
Its target architecture is the ARM, referred to by these tools as arm.\n ```
同様の変更が`src/cmd/6a/doc.go`と`src/cmd/8a/doc.go`にも適用されています。これらの変更は、各アーキテクチャのアセンブラツールが参照する公式ドキュメントのURLを、新しい簡潔なパスに更新するものです。これにより、ドキュメントへのリンク切れを防ぎ、ユーザーが常に最新の正確な情報にアクセスできるようになります。
* **タイプミスの修正 (`src/cmd/6a/doc.go`)**:
```diff
--- a/src/cmd/6a/doc.go
+++ b/src/cmd/6a/doc.go
@@ -12,9 +12,9 @@
Go-specific considerations are documented at
-\thttp://golang.org/doc/asm.html\n+\thttp://golang.org/doc/asm\n
-IIts target architecture is the x86-64, referred to by these tools as amd64.\n+Its target architecture is the x86-64, referred to by these tools as amd64.\n
*/\n package main
```
これは小さな修正ですが、ドキュメントの品質とプロフェッショナリズムを向上させるものです。
これらの変更は全体として、Goのアセンブラに関する公式ドキュメントの網羅性と正確性を大幅に向上させ、特に低レベルのスタック操作や特定のアーキテクチャ(ARM)におけるレジスタの挙動に関する開発者の理解を深めることを目的としています。
## 関連リンク
* Go CL 26170043: [https://golang.org/cl/26170043](https://golang.org/cl/26170043)
## 参考にした情報源リンク
* Go言語公式ドキュメント: A Quick Guide to Go's Assembler (このコミットで更新されたドキュメント自体)
* Go言語のソースコード (このコミットの変更差分)
* ARMアーキテクチャの基本概念に関する一般的な知識