Go Assembly Programming

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

源自 Plan9 彙編實現。 儲存在 .s 檔案中,編譯器自動編譯、連結。

本文內容基於 amd64 架構。

指令

指令參數長度。

MOVB: 1-byteMOVW: 2 MOVL: 4 MOVQ: 8 

資料移動方向:從左往右。

 ADD R1, R2        // R2 += R1 SUB R3, R4        // R4 -= R3 SUB R3, R4, R5    // R5 = R4 - R3 MUL $7, R6        // R6 *= 7

記憶體訪問。

 MOV (R1), R2            // R2 = *R1 MOV 8(R1), R2           // R2 = *(8 + R2) MOV 16(R1)(R2*2), R3    // R3 = *(16 + R1 + R2*2) MOV runtime·x(SB), R2   // R2 = *runtime·x

跳轉指令。

 JMP label      // 跳轉到標籤。 JMP 2(PC)      // 跳轉到 PC + n 行。 JMP -2(PC)

數字常量以 $ 開頭,十進位($10)和 十六進位($0x10)。 標籤僅在函數內有效。

偽寄存器

偽寄存器(pseudo-register)由語言定義並使用,最終會被編譯為硬體寄存器引用。

考慮到平台差異,編譯後的機器代碼,可能須儲存 PC、BP、SP 等物理寄存器值。 在編寫彙編代碼時,很難事先計算好實際所需位移量。為此,組合語言用偽寄存器表示某個相對位置就很有必要。

  • SB: Static Base Pointer(全域符號)

表示一個全域符號地址,通常應用於全域函數或資料。
例如 CALL add(SB) 表示對應符號名字為 add 的記憶體位址。
在名字後添加角括弧(add<>(SB)),表示該符號名僅在當前檔案內可見。
還可用位移量表示基於某個符號名字的地址,例如 add+8(SB)。

  • FP: Frame Pointer(參數地址)

指向由調用方提供的參數列表起始地址,通過位移量指向不同參數或傳回值。
通常在位移量前包含參數名。例如 MOVQ size+16(FP), AX
  • SP: Stack Pointer (棧局部變數記憶體位址)

偽 SP 寄存器表示棧幀內,用於本地局部變數操作的起始地址。
鑒於棧從底開始的操作方式,SP 實際是棧底位置(等同調整後的 BP 地址)。
使用該方式訪問局部變數,須添加變數名,如 x-8(SP)。如果省略變數名,則表示硬體寄存器。

  • PC: Program Counter(指令地址)

可用來按指令行數條轉。
比如 JMP 2(PC) 表示以當前位置為 0 基準,往下跳到第 2 行。

考慮到棧幀記憶體實際上分成局部變數(底)和調用參數(頂)兩部分使用,所以用偽 SP 寄存器負值便宜訪問局部變數是很自然的做法。 如此,物理寄存器 SP 用來操作調用參數入棧;而偽寄存器 SP 用來訪問局部變數。 畢竟 BP 寄存器是可選的。

注意 x+0(FP)gobuf_pc(AX) 宏函數的區別。

                         CALLEE  lo               SP +-----------+   ..........................                      |           |                            .                      +-----------+                            .                      |           |                       frame size(包括 caller BP)       BP (pseudo SP) +-----------+                            .                      | caller BP |                            .                      +-----------+   ..........................                      | caller PC |                   FP +-----------+------------+ SP   ..........                      | arg0      | call arg0  |               .                      +-----------+------------+               .                      | argn      | call argn  |       argument size                      +-----------+------------+               .                      | return    | call ret   |               .  hi                  +-----------+------------+   .............                                  | local var0 |                                  +------------+                                  | local varn |                                  +------------+ BP (pseudo SP)                                      CALLER

函數

函數定義。

                                          參數及傳回值大小                                          |  TEXT runtime·cgocallback(SB),NOSPLIT,$32-32       |        |                      |      包名     函數名                   棧幀大小(不包括參數及傳回值)

當前包,可省略包名,直接以中心點開始。

由調用者(caller)負責分配目標函數(callee)參數和傳回值記憶體。 調用者須自行儲存相關寄存器狀態。

樣本

使用彙編代碼編寫一個簡單的加法。

add.s

 #include "textflag.h"  // add(x, y int) int TEXT ·add(SB), NOSPLIT, $8-24     MOVQ $0, z-0x8(SP)     MOVQ x+0x0(FP), AX     MOVQ y+0x8(FP), BX     ADDQ AX, BX            MOVQ BX, z-0x8(SP)     MOVQ BX, ret+0x10(FP)     RET

main.go

 package main  func add(x, y int) (z int)    // 聲明彙編函數原型  func main() {    z := add(0x100, 0x200)    println(z) }

可以看到編譯器插入棧幀調整,環境儲存等指令。

 $ go build -gcflags "-l"  $ go tool objdump -s "main\.add" test  TEXT main.add(SB) add.s    add.s:5     0x104bfe0       SUBQ $0x10, SP        // 因為要儲存 BP,所以棧幀大小調整到 0x10。    add.s:5     0x104bfe4       MOVQ BP, 0x8(SP)        add.s:5     0x104bfe9       LEAQ 0x8(SP), BP         add.s:6     0x104bfee       MOVQ $0x0, 0(SP)        add.s:7     0x104bff6       MOVQ 0x18(SP), AX       add.s:8     0x104bffb       MOVQ 0x20(SP), BX       add.s:9     0x104c000       ADDQ AX, BX         add.s:10    0x104c003       MOVQ BX, 0(SP)          add.s:11    0x104c007       MOVQ BX, 0x28(SP)       add.s:12    0x104c00c       MOVQ 0x8(SP), BP         add.s:12    0x104c011       ADDQ $0x10, SP        // 清除棧幀。    add.s:12    0x104c015       RET     

使用 -gcflags -S 輸出反組譯碼時,會有 FUNCDATA 和 PCDATA 資訊。 它們是編譯器引入,包含記憶體回收行程要使用的資訊。

323 次點擊  
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.