Go語言匯編


Plan 9匯編

寄存器:

數據寄存器:R0-R7,地址寄存器:A0-A7,浮點寄存器:F0-F7。

偽棧寄存器:FP, SP, TOS。

FP是frame pointer,0(FP)是第一個參數,4(FP)是第二個。

SP是local stack pointer,保存自動變量。0(SP)是第一個。

TOS是top of stack寄存器,用來保存過程的參數,保存局部變量。

匯編器可以有一個變量名,比如p+0(FP),表示p是第一個參數,這個變量保存在符號表內,但是對程序運行沒有影響。

數據:

所有的外部引用都需通過偽寄存器: PC(virtual Program Counter)/SB(Static Base register)。

PC用來控制程序執行,SB用來引用全局變量。比如:

把全局數組的地址壓棧:MOVL $array(SB), TOS。

把全局數組的第二個元素壓棧:MOVL array+4(SB), TOS

local<>+4(SB)是本地變量,只在本文件可見。

定義流程:

TEXT sum(SB), $0

TEXT是一個偽指令,用來定義入口點。后面的參數是函數名,然后是棧大小,通常為0。

中間可以有一個指定loader的選項,設置為1暫停函數的profiling。

設置為2允許一個程序中有多個TEXT符號。

子流程把運算結果放到R0中。浮點的結果放在F0中。

子流程負責保存自己的寄存器,為caller saves模式。

 Go語言匯編

Go語言的匯編基於Plan 9的匯編,但是有一些不同。最主要的一個區別是,Go語言的匯編指令不一定直接對應機器表示。有一些直接對應,有一些則不是。

編譯器產生的是一些中間碼,具體的機器指令是在匯編生成之后才定下來的(Linker的工作)。

FUNCDATA和PCDATA是編譯器產生的,用於保存一些給垃圾收集的信息。

Go語言的匯編和Plan 9的另一個不同是操作符的優先級。比如3&1<<2被解釋成(3&1)<<2。

符號:

Go語言有4個偽寄存器,實際是對內存位置的一個引用。

FP: 幀指針,保存參數和本地變量

PC:程序指針,負責跳轉和流程控制

SB: 靜態基指針,全局變量

SP:棧指針,棧頂

所有的符號全部攜程FP和SB的偏移的形式:

SB偽寄存器用來表示全局的變量或者函數,不如foo(SB)用來表示foo的地址。加<>表示符號本文件內可見。

FP是用來保存參數的。(0)FP是第一個參數(8)FP是第二個(如果是64位機器)。

SP指向本地棧頂,分別用x-8(SP), y-4(SP)表示變量。

直接的jmp或者call指令,只能指向text符號,不能是符號的偏移。

指令:

TEXT指令定義一個符號,后面緊跟函數體。

DATA指令定義一個section的內存,這段內存並不會被初始化。

DATA    symbol+offset(SB)/width, value

GLOBAL指令定義一個符號是全局的

GLOBL divtab<>(SB), RODATA, $64

GLOBL runtime·tlsoffset(SB), NOPTR, $4

divtab是制度的64byte的表格,保存4個byte的整形。tlsoffset是,4byte的no pointers

指令修飾符:

DUPOK:允許一個二進制文件里有多個實例

NOSPLIT: FOR TEXT,routine或者routine的子函數,必須把棧的空間的頭填滿,用來保護棧分隔

RODATA:FOR DATA/GLOBL,把數據放在只讀段

NOPTR: FOR DATA/GLOBL,數據沒有指針,不需要被垃圾收集掃描

WRAPPER: FOR TEXT,wrapper function,不需要被以禁用recover計數

NEEDCTXT:FOR TEXT,閉包

Runtime協作:

NOPTR和RODATA的數據不需要被垃圾收集。比指針還要小的數據也被當做NOPTR。不要在go匯編里寫非只讀數據。

語法:

plan9函數調用協議中采用的是caller-save的模式,也就是由調用者負責保存寄存器。

TEXT !$Add(SB),$0
    MOVQ x+0(FP), BX
    MOVQ y+8(FP), BP
    ADDQ BP, BX
    MOVQ BX, ret+16(FP)
    RET

a+8(FP)

變量名+偏移(寄存器)。FP其實就是BP(棧基址寄存器上移一個機器字長位置的內存地址)。

TEXT ·add(SB),NOSPLIT,$0

00B7分隔了包名和變量名。NOSPLIT表示不用寫入參數的大小,$0表示參數的大小,因為制定了NOSPLIT所以寫0

匯編文件的名字甚至變量名稱並不重要。

MOVQ $0, DX //put 0 into DX register. Q means quadword which is 8 bytes. L for 4 bytes. (src, destination) order

¥24-8表示24字節的幀,和8個字節的參數

Go Array有不是指向第一個元素的指針,而是代表整個數組。賦值或者傳遞的時候是有一個copy的。

Go slice有三個部分, 一個指針,一個長度,一個容量,指針8個字節,長度和容量4個字節

一個slice沒有固定的長度。slice不能指定長度。一個slice如果要增加capacity必須創建一個新的容量更大的slice,並copy內容過去。

 

Examples:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM