Golang彙編快速指南

2021-10-07 01:26:21 字數 3518 閱讀 2627

有些符號,例如pcr0sp,是預定義的並且是對乙個暫存器的引用。 另外還有兩種預定義的符號,sb(static base)和fp(frame pointer)。 所有使用者定義的符號,除了標籤跳轉之外,都是對偽暫存器的offsets操作。

1)sb偽暫存器可以想象成記憶體的位址,所以符號foo(sb)是乙個由foo這個名字代表的記憶體位址。這種形式一般用來命名全域性函式和資料。給名字增加乙個<>符號,就像foo<>(sb),會讓這個名字只有在當前檔案可見,就像在c檔案中預定義的static

2)fp偽暫存器是乙個虛擬的幀指標,用來指向函式的引數。編譯器維護了乙個虛擬的棧指標,使用對偽暫存器的offsets操作的形式,指向棧上的函式引數。 於是,0(fp)就是第乙個引數,8(fp)就是第二個(64位機器),以此類推。 當用這種方式引用函式引數時,可以很方便的在符號前面加上乙個名稱,就像first_arg+0(fp)second_arg+8(fp)。有些匯程式設計序強制使用這種約定,禁止單一的0(fp)8(fp)。在使用go標準定義的彙編函式中,go vet會檢查引數的名字和它們的匹配範圍。 在32位系統上,乙個64位值的高32和低32位表示為增加_lo_hi這個兩個字尾到乙個名稱,就像arg_lo+0(fp)或者arg_hi+4(fp)。如果乙個go原型函式沒有命名它的結果,期待的名字將會被返回。

在go物件檔案和二進位制檔案中,符號的完整名字是包的路徑加上乙個句點:fmt.printfmath/rand.int。但是彙編器會把句點和斜槓當做標點符號來對待,這些字元不能當做符號的識別符號。取而代之的是,允許在匯程式設計序中使用中點字元(unicode字元00b7)和除法斜槓(原文中是division slash,unicode字元2215,區別於forward slash)當做識別符號並且把它們重寫成純句點和斜槓。 在組合語言的原始檔中,上面的符號寫成fmt·printfmath∕rand.int。 通過在編譯時使用-s標誌看到的彙編**列表中直接顯示了句點和斜槓,而不是在匯程式設計序中需要的unicode替代字元(指上面的兩個特殊unicode字元)。

大部分手寫的彙編檔案中,不要在符號名中包含完整的包路徑,因為鏈結器會在任何以句點開頭的名字前面插入當前物件檔案的路徑:在math/rand包的彙編原始檔中,rand包的int函式被當做了·int來引用。這種便捷性避免了需要在自身的源**中硬編碼匯入路徑,可以讓**從乙個地方移動到另乙個地方時變得更容易。

匯程式設計序中使用多種指令繫結文字和資料到符號名。舉個例子,下面有乙個簡單但是完整的函式定義。text指令宣告了符號runtime·profileloop,指令緊接在類似於函式的主體中。text塊的最後必須是某種形式的跳轉,通常是乙個ret(偽)指令。(如果沒有,鏈結器會追加乙個跳轉到塊自身的指令,text塊中沒有fallthrough) 符號的後面,引數是標誌棧幀的大小,是乙個常量(但是看下面的**):

text runtime·profileloop(sb),nosplit,$8

movq $runtime·profileloop1(sb), cx

movq cx, 0(sp)

call runtime·externalthreadhandler(sb)

ret

這個函式的棧幀大小為8位元組(movq cx, 0(sp)操作棧指標),沒有引數

一般情況下,棧幀的大小跟在引數的大小之後,由乙個減法符號分隔。(它不是減號,只是特殊的語法) 棧幀大小是$24-8描述了函式有24位元組的棧幀並且需要乙個8位元組的引數,存在於呼叫者的棧幀中。如果沒有為text指定nosplit標誌,必須提供引數大小。在使用go標準定義的彙編函式中,go vet會檢查引數大小是否正確。

注意符號名是使用中點來分割元件的,並且被定義為從偽暫存器sb開始的乙個offsets。在go原始碼的runtime包中,使用簡稱profileloop來呼叫。

全域性資料符號使用初始化的一系列data指令來定義,並且跟在乙個global指令之後。每個data指令初始化一塊指定的記憶體區域。沒有明確初始化的記憶體區域會被置為零。標準的data指令形式為:

data    symbol+offset(sb)/width, value
這樣就初始化了symbol,內存在指定的offset處,帶有指定的width和給定的value。乙個symbol中的data指令必須是逐漸增長的offsets。

global指令將乙個symbol宣告為全域性的。引數是可選的標誌和需要宣告為全域性的資料的大小,並會初始化為零值,除非data指令中已經初始化它。global指令必須跟在對應的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

宣告並且初始化了divtab<>,乙個唯讀的64位table含有4位元組的整數值。 並且宣告了runtime·tlsoffset,乙個4位元組並且明確被零值初始化的值,其中不含有指標。

指令可以含有乙個或者兩個引數。如果有兩個引數,第乙個是位元掩碼的標誌,可以寫成數字的表示式,多個掩碼之間可以相加或者做邏輯或運算,或者可以寫成友好可讀的形式。這些值定義在標頭檔案textflag.h中:

此文為官方文件的翻譯:

golang 數字比較 彙編分析golang迴圈

女主宣言 ps 豐富的一線技術 多元化的表現形式,盡在 360雲計算 點關注哦!迴圈是程式設計中很強大的乙個概念,而且非常容易處理。但是,必須將其翻譯成機器可理解的基本指令。它的編譯方式也可能影響標準庫中的其他元件。讓我們開始分析一下範圍迴圈。迴圈彙編 範圍迴圈可以迭代陣列,切片或通道。下面函式展示...

學習指南 goLang

我是從python轉向go的.起始版本是go 1.1.主要看a tour of go,how to write go code,effective go 2 熟悉package,3 練習,project eular.每學一門新語言的時候,可以來做一遍.about project euler 4 語言...

彙編入門指南

2.介紹 常見概念 3.推薦資源 本教程按照作者親身經歷和 x86組合語言 從實模式到保護模式 寫成 為什麼要學彙編?眾所周知,彙編是比較早期的一種程式語言和低階語言,雖然比不上高階語言的可讀性和效率,但這種語言作為最接近機器碼的語言可以很好的幫助我們了解最底層相關機制。mov指令是資料傳送指令 如...