<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 1.4 Plan 9 匯編語言 本節我們快速介紹 Go 語言使用的 Plan 9 匯編,以方便在后續章節中能夠流暢的閱讀 Go 源碼中關于匯編的部分。 對于一段 Go 程序,我們可以通過下面的命令來獲得編譯后的匯編代碼: ``` go build -gcflags "-N -l" -ldflags=-compressdwarf=false -o main.out main.go go tool objdump -s "main.main" main.out &gt; main.S # or go tool compile -S main.go # or go build -gcflags -S main.go ``` FUNCDATA 和 PCDATA 指令包含了由垃圾回收器使用的信息,他們由編譯器引入。 ## 常量 ## 符號 ## 指令 全局數據符號由以 DATA 指令開頭的序列 全局數據符號由一系列以 DATA 指令起始和一個 GLOBL 指令定義。 每個 DATA 指令初始化相應內存的一部分。未明確初始化的內存為零。 該 DATA 指令的一般形式是 ~~~ DATA symbol+offset(SB)/width, value ~~~ 在給定的 offset 和 width 處初始化該符號的內存為 value。 DATA 必須使用增加的偏移量來寫入給定符號的指令。 該 GLOBL 指令聲明符號是全局的。參數是可選標志,并且數據的大小被聲明為全局, 除非 DATA 指令已初始化,否則初始值將全為零。該 GLOBL 指令必須遵循任何相應的 DATA 指令。 例如: ~~~ DATA divtab<>+0x00(SB)/4, $0xf4f8fcff DATA divtab<>+0x04(SB)/4, $0xe6eaedf0 ... DATA divtab<>+0x3c(SB)/4, $0x81828384 GLOBL divtab<>(SB), RODATA, $64 GLOBL runtime·tlsoffset(SB), NOPTR, $4 ~~~ | 指令 | 操作符 | 解釋 | | :-- | :-- | :-- | | JMP | | | | MOVL | | | | MOVQ | | | | MOVEQ | | | | LEAQ | | | | SUBQ | | | | ANDQ | | | | CALL | | | | PUSHQ | | | | POPQ | | | | CLD | | | | CMPQ | | | | CPUID | | | | JEQ | | | ## 運行時協調 為保證垃圾回收正確運行,在大多數棧幀中,運行時必須知道所有全局數據的指針。 Go 編譯器會將這部分信息耦合到 Go 源碼文件中,但匯編程序必須進行顯式定義。 被標記為`NOPTR`標志的數據符號會視為不包含指向運行時分配數據的指針。 帶有`R0DATA`標志的數據符號在只讀存儲器中分配,因此被隱式標記為`NOPTR`。 總大小小于指針的數據符號也被視為隱式標記`NOPTR`。 在一份匯編源文件中是無法定義包含指針的符號的,因此這種符號必須定義在 Go 原文件中。 一個良好的經驗法則是`R0DATA`在 Go 中定義所有非符號而不是在匯編中定義。 每個函數還需要注釋,在其參數,結果和本地堆棧框架中給出實時指針的位置。 對于沒有指針結果且沒有本地堆棧幀或沒有函數調用的匯編函數, 唯一的要求是在同一個包中的 Go 源文件中為函數定義 Go 原型。 匯編函數的名稱不能包含包名稱組件 (例如,`syscall`包中的函數`Syscall`應使用名稱`·Syscall`而不是`syscall·Syscall`其TEXT指令中的等效名稱)。 對于更復雜的情況,需要顯式注釋。 這些注釋使用標準`#include`文件中定義的偽指令`funcdata.h`。 如果函數沒有參數且沒有結果,則可以省略指針信息。這是由一個參數大小`$n-0`注釋指示`TEXT`對指令。 否則,指針信息必須由Go源文件中的函數的Go原型提供,即使對于未直接從Go調用的匯編函數也是如此。 (原型也將`go vet`檢查參數引用。)在函數的開頭,假定參數被初始化但結果假定未初始化。 如果結果將在調用指令期間保存實時指針,則該函數應首先將結果歸零, 然后執行偽指令`GO_RESULTS_INITIALIZED`。 此指令記錄結果現在已初始化,應在堆棧移動和垃圾回收期間進行掃描。 通常更容易安排匯編函數不返回指針或不包含調用指令; 標準庫中沒有匯編函數使用`GO_RESULTS_INITIALIZED`。 如果函數沒有本地堆棧幀,則可以省略指針信息。這由`TEXT`指令上的本地幀大小`$0-n`注釋表示。如果函數不包含調用指令,也可以省略指針信息。否則,本地堆棧幀不能包含指針,并且匯編必須通過執行偽指令`TEXTNO_LOCAL_POINTERS`來確認這一事實。因為通過移動堆棧來實現堆棧大小調整,所以堆棧指針可能在任何函數調用期間發生變化:甚至指向堆棧數據的指針也不能保存在局部變量中。 匯編函數應始終給出 Go 原型,既可以提供參數和結果的指針信息,也可以`go vet`檢查用于訪問它們的偏移量是否正確。 ## 寄存器 ### 通用寄存器 Plan 9 中的通用寄存器包括: AX BX CX DX DI SI BP SP R8 R9 R10 R11 R12 R13 R14 PC ### 偽寄存器 偽寄存器不是真正的寄存器,而是由工具鏈維護的虛擬寄存器,例如幀指針。 FP, Frame Pointer:幀指針,參數和本地 PC, Program Counter: 程序計數器,跳轉和分支 SB, Static Base: 靜態基指針, 全局符號 SP, Stack Pointer: 當前棧幀開始的地方 所有用戶定義的符號都作為偏移量寫入偽寄存器 FP 和 SB。 ## 尋址模式 匯編語言的一個很重要的概念就是它的尋址模式,Plan 9 匯編也不例外,它支持如下尋址模式: ~~~ R0 數據寄存器 A0 地址寄存器 F0 浮點寄存器 CAAR, CACR, 等 特殊名字 $con 常量 $fcon 浮點數常量 name+o(SB) 外部符號 name<>+o(SB) 局部符號 name+o(SP) 自動符號 name+o(FP) 實際參數 $name+o(SB) 外部地址 $name<>+o(SB) 局部地址 (A0)+ 間接后增量 -(A0) 間接前增量 o(A0) o()(R0.s) symbol+offset(SP) 引用函數的局部變量,offset 的合法取值是 [-framesize, 0) 局部變量都是 8 字節,那么第一個局部變量就可以用 localvar0-8(SP) 來表示 如果是 symbol+offset(SP) 形式,則表示偽寄存器 SP 如果是 offset(SP) 則表示硬件寄存器 SP ~~~ ``` TEXT pkgname·funcname(SB),NOSPLIT,$-8 JMP _rt0_amd64(SB) ``` ## 進一步閱讀的參考文獻 * [A Quick Guide to Go's Assembler](https://golang.org/doc/asm) * [Rob Pike, How to Use the Plan 9 C Compiler](http://doc.cat-v.org/plan_9/2nd_edition/papers/comp) * [Rob Pike, A Manual for the Plan 9 assembler](https://9p.io/sys/doc/asm.html) * [Debugging Go Code with GDB](https://golang.org/doc/gdb)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看