Go 語(yǔ)言 計(jì)算機(jī)結(jié)構(gòu)

2023-03-22 15:01 更新

原文鏈接:https://chai2010.cn/advanced-go-programming-book/ch3-asm/ch3-02-arch.html


3.2 計(jì)算機(jī)結(jié)構(gòu)

匯編語(yǔ)言是直面計(jì)算機(jī)的編程語(yǔ)言,因此理解計(jì)算機(jī)結(jié)構(gòu)是掌握匯編語(yǔ)言的前提。當(dāng)前流行的計(jì)算機(jī)基本采用的是馮·諾伊曼計(jì)算機(jī)體系結(jié)構(gòu)(在某些特殊領(lǐng)域還有哈佛體系架構(gòu))。馮·諾依曼結(jié)構(gòu)也稱為普林斯頓結(jié)構(gòu),采用的是一種將程序指令和數(shù)據(jù)存儲(chǔ)在一起的存儲(chǔ)結(jié)構(gòu)。馮·諾伊曼計(jì)算機(jī)中的指令和數(shù)據(jù)存儲(chǔ)器其實(shí)指的是計(jì)算機(jī)中的內(nèi)存,然后在配合 CPU 處理器就組成了一個(gè)最簡(jiǎn)單的計(jì)算機(jī)了。

匯編語(yǔ)言其實(shí)是一種非常簡(jiǎn)單的編程語(yǔ)言,因?yàn)樗嫦虻挠?jì)算機(jī)模型就是非常簡(jiǎn)單的。讓人覺(jué)得匯編語(yǔ)言難學(xué)主要有幾個(gè)原因:不同類型的 CPU 都有自己的一套指令;即使是相同的 CPU,32 位和 64 位的運(yùn)行模式依然會(huì)有差異;不同的匯編工具同樣有自己特有的匯編指令;不同的操作系統(tǒng)和高級(jí)編程語(yǔ)言和底層匯編的調(diào)用規(guī)范并不相同。本節(jié)將描述幾個(gè)有趣的匯編語(yǔ)言模型,最后精簡(jiǎn)出一個(gè)適用于 AMD64 架構(gòu)的精簡(jiǎn)指令集,以便于 Go 匯編語(yǔ)言的學(xué)習(xí)。

3.2.1 圖靈機(jī)和 BF 語(yǔ)言

圖靈機(jī)是由圖靈提出的一種抽象計(jì)算模型。機(jī)器有一條無(wú)限長(zhǎng)的紙帶,紙帶分成了一個(gè)一個(gè)的小方格,每個(gè)方格有不同的顏色,這類似于計(jì)算機(jī)中的內(nèi)存。同時(shí)機(jī)器有一個(gè)探頭在紙帶上移來(lái)移去,類似于通過(guò)內(nèi)存地址來(lái)讀寫內(nèi)存上的數(shù)據(jù)。機(jī)器頭有一組內(nèi)部計(jì)算狀態(tài),還有一些固定的程序(更像一個(gè)哈佛結(jié)構(gòu))。在每個(gè)時(shí)刻,機(jī)器頭都要從當(dāng)前紙帶上讀入一個(gè)方格信息,然后根據(jù)自己的內(nèi)部狀態(tài)和當(dāng)前要執(zhí)行的程序指令將信息輸出到紙帶方格上,同時(shí)更新自己的內(nèi)部狀態(tài)并進(jìn)行移動(dòng)。

圖靈機(jī)雖然不容易編程,但是非常容易理解。有一種極小化的 BrainFuck 計(jì)算機(jī)語(yǔ)言,它的工作模式和圖靈機(jī)非常相似。BrainFuck 由 Urban Müller 在 1993 年創(chuàng)建的,簡(jiǎn)稱為 BF 語(yǔ)言。Müller 最初的設(shè)計(jì)目標(biāo)是建立一種簡(jiǎn)單的、可以用最小的編譯器來(lái)實(shí)現(xiàn)的、符合圖靈完全思想的編程語(yǔ)言。這種語(yǔ)言由八種狀態(tài)構(gòu)成,早期為 Amiga 機(jī)器編寫的編譯器(第二版)只有 240 個(gè)字節(jié)大??!

就象它的名字所暗示的,brainfuck 程序很難讀懂。盡管如此,brainfuck 圖靈機(jī)一樣可以完成任何計(jì)算任務(wù)。雖然 brainfuck 的計(jì)算方式如此與眾不同,但它確實(shí)能夠正確運(yùn)行。這種語(yǔ)言基于一個(gè)簡(jiǎn)單的機(jī)器模型,除了指令,這個(gè)機(jī)器還包括:一個(gè)以字節(jié)為單位、被初始化為零的數(shù)組、一個(gè)指向該數(shù)組的指針(初始時(shí)指向數(shù)組的第一個(gè)字節(jié))、以及用于輸入輸出的兩個(gè)字節(jié)流。這是一種按照?qǐng)D靈完備的語(yǔ)言,它的主要設(shè)計(jì)思路是:用最小的概念實(shí)現(xiàn)一種 “簡(jiǎn)單” 的語(yǔ)言。BrainFuck 語(yǔ)言只有八種符號(hào),所有的操作都由這八種符號(hào)的組合來(lái)完成。

下面是這八種狀態(tài)的描述,其中每個(gè)狀態(tài)由一個(gè)字符標(biāo)識(shí):

字符 C 語(yǔ)言類比 含義
> ++ptr; 指針加一
< --ptr; 指針減一
+ ++*ptr; 指針指向的字節(jié)的值加一
- --*ptr; 指針指向的字節(jié)的值減一
. putchar(*ptr); 輸出指針指向的單元內(nèi)容(ASCⅡ 碼)
, *ptr = getch(); 輸入內(nèi)容到指針指向的單元(ASCⅡ 碼)
[ while(*ptr) {} 如果指針指向的單元值為零,向后跳轉(zhuǎn)到對(duì)應(yīng)的 ] 指令的次一指令處
] 如果指針指向的單元值不為零,向前跳轉(zhuǎn)到對(duì)應(yīng)的 [ 指令的次一指令處

下面是一個(gè) brainfuck 程序,向標(biāo)準(zhǔn)輸出打印 "hi" 字符串:

++++++++++[>++++++++++<-]>++++.+.

理論上我們可以將 BF 語(yǔ)言當(dāng)作目標(biāo)機(jī)器語(yǔ)言,將其它高級(jí)語(yǔ)言編譯為 BF 語(yǔ)言后就可以在 BF 機(jī)器上運(yùn)行了。

3.2.2 人力資源機(jī)器游戲

《人力資源機(jī)器》(Human Resource Machine)是一款設(shè)計(jì)精良匯編語(yǔ)言編程游戲。在游戲中,玩家扮演一個(gè)職員角色,來(lái)模擬人力資源機(jī)器的運(yùn)行。通過(guò)完成上司給的每一份任務(wù)來(lái)實(shí)現(xiàn)晉升的目標(biāo),完成任務(wù)的途徑就是用游戲提供的 11 個(gè)機(jī)器指令編寫正確的匯編程序,最終得到正確的輸出結(jié)果。人力資源機(jī)器的匯編語(yǔ)言可以認(rèn)為是跨平臺(tái)、跨操作系統(tǒng)的通用的匯編語(yǔ)言,因?yàn)樵?macOS、Windows、Linux 和 iOS 上該游戲的玩法都是完全一致的。

人力資源機(jī)器的機(jī)器模型非常簡(jiǎn)單:INBOX 命令對(duì)應(yīng)輸入設(shè)備,OUTBOX 對(duì)應(yīng)輸出設(shè)備,玩家小人對(duì)應(yīng)一個(gè)寄存器,臨時(shí)存放數(shù)據(jù)的地板對(duì)應(yīng)內(nèi)存,然后是數(shù)據(jù)傳輸、加減、跳轉(zhuǎn)等基本的指令。總共有 11 個(gè)機(jī)器指令:

名稱 解釋
INBOX 從輸入通道取一個(gè)整數(shù)數(shù)據(jù),放到手中 (寄存器)
OUTBOX 將手中(寄存器)的數(shù)據(jù)放到輸出通道,然后手中將沒(méi)有數(shù)據(jù)(此時(shí)有些指令不能運(yùn)行)
COPYFROM 將地板上某個(gè)編號(hào)的格子中的數(shù)據(jù)復(fù)制到手中(手中之前的數(shù)據(jù)作廢),地板格子必須有數(shù)據(jù)
COPYTO 將手中(寄存器)的數(shù)據(jù)復(fù)制到地板上某個(gè)編號(hào)的格子中,手中的數(shù)據(jù)不變
ADD 將手中(寄存器)的數(shù)據(jù)和某個(gè)編號(hào)對(duì)應(yīng)的地板格子的數(shù)據(jù)相加,新數(shù)據(jù)放到手中(手中之前的數(shù)據(jù)作廢)
SUB 將手中(寄存器)的數(shù)據(jù)和某個(gè)編號(hào)對(duì)應(yīng)的地板格子的數(shù)據(jù)相減,新數(shù)據(jù)放到手中(手中之前的數(shù)據(jù)作廢)
BUMP+ 自加一
BUMP- 自減一
JUMP 跳轉(zhuǎn)
JUMP =0 為零條件跳轉(zhuǎn)
JUMP <0 為負(fù)條件跳轉(zhuǎn)

除了機(jī)器指令外,游戲中有些環(huán)節(jié)還提供類似寄存器的場(chǎng)所,用于存放臨時(shí)的數(shù)據(jù)。人力資源機(jī)器游戲的機(jī)器指令主要分為以下幾類:

  • 輸入/輸出 (?INBOX?/?OUTBOX?): 輸入后手中將只有 1 份新拿到的數(shù)據(jù), 輸出后手中將沒(méi)有數(shù)據(jù)。
  • 數(shù)據(jù)傳輸指令 (?COPYFROM?/?COPYTO?): 主要用于僅有的 1 個(gè)寄存器(手中)和內(nèi)存之間的數(shù)據(jù)傳輸,傳輸時(shí)要確保源數(shù)據(jù)是有效的
  • 算術(shù)相關(guān) (?ADD?/?SUB?/?BUMP+?/?BUMP-?)
  • 跳轉(zhuǎn)指令: 如果是條件跳轉(zhuǎn),寄存器中必須要有數(shù)據(jù)

主流的處理器也有類似的指令。除了基本的算術(shù)和邏輯運(yùn)算指令外,再配合有條件跳轉(zhuǎn)指令就可以實(shí)現(xiàn)分支、循環(huán)等常見(jiàn)控制流結(jié)構(gòu)了。

下圖是某一層的任務(wù):將輸入數(shù)據(jù)的 0 剔除,非 0 的數(shù)據(jù)依次輸出,右邊部分是解決方案。


圖 3-1 人力資源機(jī)器

整個(gè)程序只有一個(gè)輸入指令、一個(gè)輸出指令和兩個(gè)跳轉(zhuǎn)指令共四個(gè)指令:

LOOP:
    INBOX
    JUMP-if-zero LOOP
    OUTBOX
    JUMP LOOP

首先通過(guò) INBOX 指令讀取一個(gè)數(shù)據(jù)包;然后判斷包裹的數(shù)據(jù)是否為 0,如果是 0 的話就跳轉(zhuǎn)到開(kāi)頭繼續(xù)讀取下一個(gè)數(shù)據(jù)包;否則將輸出數(shù)據(jù)包,然后再跳轉(zhuǎn)到開(kāi)頭。以此循環(huán)無(wú)休止地處理數(shù)據(jù)包裹,直到任務(wù)完成晉升到更高一級(jí)的崗位,然后處理類似的但更復(fù)雜的任務(wù)。

3.2.3 X86-64 體系結(jié)構(gòu)

X86 其實(shí)是是 80X86 的簡(jiǎn)稱(后面三個(gè)字母),包括 Intel 8086、80286、80386 以及 80486 等指令集合,因此其架構(gòu)被稱為 x86 架構(gòu)。x86-64 是 AMD 公司于 1999 年設(shè)計(jì)的 x86 架構(gòu)的 64 位拓展,向后兼容于 16 位及 32 位的 x86 架構(gòu)。X86-64 目前正式名稱為 AMD64,也就是 Go 語(yǔ)言中 GOARCH 環(huán)境變量指定的 AMD64。如果沒(méi)有特殊說(shuō)明的話,本章中的匯編程序都是針對(duì) 64 位的 X86-64 環(huán)境。

在使用匯編語(yǔ)言之前必須要了解對(duì)應(yīng)的 CPU 體系結(jié)構(gòu)。下面是 X86/AMD 架構(gòu)圖:


圖 3-2 AMD64 架構(gòu)

左邊是內(nèi)存部分是常見(jiàn)的內(nèi)存布局。其中 text 一般對(duì)應(yīng)代碼段,用于存儲(chǔ)要執(zhí)行指令數(shù)據(jù),代碼段一般是只讀的。然后是 rodata 和 data 數(shù)據(jù)段,數(shù)據(jù)段一般用于存放全局的數(shù)據(jù),其中 rodata 是只讀的數(shù)據(jù)段。而 heap 段則用于管理動(dòng)態(tài)的數(shù)據(jù),stack 段用于管理每個(gè)函數(shù)調(diào)用時(shí)相關(guān)的數(shù)據(jù)。在匯編語(yǔ)言中一般重點(diǎn)關(guān)注 text 代碼段和 data 數(shù)據(jù)段,因此 Go 匯編語(yǔ)言中專門提供了對(duì)應(yīng) TEXT 和 DATA 命令用于定義代碼和數(shù)據(jù)。

中間是 X86 提供的寄存器。寄存器是 CPU 中最重要的資源,每個(gè)要處理的內(nèi)存數(shù)據(jù)原則上需要先放到寄存器中才能由 CPU 處理,同時(shí)寄存器中處理完的結(jié)果需要再存入內(nèi)存。X86 中除了狀態(tài)寄存器 FLAGS 和指令寄存器 IP 兩個(gè)特殊的寄存器外,還有 AX、BX、CX、DX、SI、DI、BP、SP 幾個(gè)通用寄存器。在 X86-64 中又增加了八個(gè)以 R8-R15 方式命名的通用寄存器。因?yàn)闅v史的原因 R0-R7 并不是通用寄存器,它們只是 X87 開(kāi)始引入的 MMX 指令專有的寄存器。在通用寄存器中 BP 和 SP 是兩個(gè)比較特殊的寄存器:其中 BP 用于記錄當(dāng)前函數(shù)幀的開(kāi)始位置,和函數(shù)調(diào)用相關(guān)的指令會(huì)隱式地影響 BP 的值;SP 則對(duì)應(yīng)當(dāng)前棧指針的位置,和棧相關(guān)的指令會(huì)隱式地影響 SP 的值;而某些調(diào)試工具需要 BP 寄存器才能正常工作。

右邊是 X86 的指令集。CPU 是由指令和寄存器組成,指令是每個(gè) CPU 內(nèi)置的算法,指令處理的對(duì)象就是全部的寄存器和內(nèi)存。我們可以將每個(gè)指令看作是 CPU 內(nèi)置標(biāo)準(zhǔn)庫(kù)中提供的一個(gè)個(gè)函數(shù),然后基于這些函數(shù)構(gòu)造更復(fù)雜的程序的過(guò)程就是用匯編語(yǔ)言編程的過(guò)程。

3.2.4 Go 匯編中的偽寄存器

Go 匯編為了簡(jiǎn)化匯編代碼的編寫,引入了 PC、FP、SP、SB 四個(gè)偽寄存器。四個(gè)偽寄存器加其它的通用寄存器就是 Go 匯編語(yǔ)言對(duì) CPU 的重新抽象,該抽象的結(jié)構(gòu)也適用于其它非 X86 類型的體系結(jié)構(gòu)。

四個(gè)偽寄存器和 X86/AMD64 的內(nèi)存和寄存器的相互關(guān)系如下圖:


圖 3-3 Go 匯編的偽寄存器

在 AMD64 環(huán)境,偽 PC 寄存器其實(shí)是 IP 指令計(jì)數(shù)器寄存器的別名。偽 FP 寄存器對(duì)應(yīng)的是函數(shù)的幀指針,一般用來(lái)訪問(wèn)函數(shù)的參數(shù)和返回值。偽 SP 棧指針對(duì)應(yīng)的是當(dāng)前函數(shù)棧幀的底部(不包括參數(shù)和返回值部分),一般用于定位局部變量。偽 SP 是一個(gè)比較特殊的寄存器,因?yàn)檫€存在一個(gè)同名的 SP 真寄存器。真 SP 寄存器對(duì)應(yīng)的是棧的頂部,一般用于定位調(diào)用其它函數(shù)的參數(shù)和返回值。

當(dāng)需要區(qū)分偽寄存器和真寄存器的時(shí)候只需要記住一點(diǎn):偽寄存器一般需要一個(gè)標(biāo)識(shí)符和偏移量為前綴,如果沒(méi)有標(biāo)識(shí)符前綴則是真寄存器。比如 (SP)、+8(SP) 沒(méi)有標(biāo)識(shí)符前綴為真 SP 寄存器,而 a(SP)b+8(SP) 有標(biāo)識(shí)符為前綴表示偽寄存器。

3.2.5 X86-64 指令集

很多匯編語(yǔ)言的教程都會(huì)強(qiáng)調(diào)匯編語(yǔ)言是不可移植的。嚴(yán)格來(lái)說(shuō)匯編語(yǔ)言是在不同的 CPU 類型、或不同的操作系統(tǒng)環(huán)境、或不同的匯編工具鏈下是不可移植的,而在同一種 CPU 中運(yùn)行的機(jī)器指令是完全一樣的。匯編語(yǔ)言這種不可移植性正是其普及的一個(gè)極大的障礙。雖然 CPU 指令集的差異是導(dǎo)致不好移植的較大因素,但是匯編語(yǔ)言的相關(guān)工具鏈對(duì)此也有不可推卸的責(zé)任。而源自 Plan9 的 Go 匯編語(yǔ)言對(duì)此做了一定的改進(jìn):首先 Go 匯編語(yǔ)言在相同 CPU 架構(gòu)上是完全一致的,也就是屏蔽了操作系統(tǒng)的差異;同時(shí) Go 匯編語(yǔ)言將一些基礎(chǔ)并且類似的指令抽象為相同名字的偽指令,從而減少不同 CPU 架構(gòu)下匯編代碼的差異(寄存器名字和數(shù)量的差異是一直存在的)。本節(jié)的目的也是找出一個(gè)較小的精簡(jiǎn)指令集,以簡(jiǎn)化 Go 匯編語(yǔ)言的學(xué)習(xí)。

X86 是一個(gè)極其復(fù)雜的系統(tǒng),有人統(tǒng)計(jì) x86-64 中指令有將近一千個(gè)之多。不僅僅如此,X86 中的很多單個(gè)指令的功能也非常強(qiáng)大,比如有論文證明了僅僅一個(gè) MOV 指令就可以構(gòu)成一個(gè)圖靈完備的系統(tǒng)。以上這是兩種極端情況,太多的指令和太少的指令都不利于匯編程序的編寫,但是也從側(cè)面體現(xiàn)了 MOV 指令的重要性。

通用的基礎(chǔ)機(jī)器指令大概可以分為數(shù)據(jù)傳輸指令、算術(shù)運(yùn)算和邏輯運(yùn)算指令、控制流指令和其它指令等幾類。因此我們可以嘗試精簡(jiǎn)出一個(gè) X86-64 指令集,以便于 Go 匯編語(yǔ)言的學(xué)習(xí)。

因此我們先看看重要的 MOV 指令。其中 MOV 指令可以用于將字面值移動(dòng)到寄存器、字面值移到內(nèi)存、寄存器之間的數(shù)據(jù)傳輸、寄存器和內(nèi)存之間的數(shù)據(jù)傳輸。需要注意的是,MOV 傳輸指令的內(nèi)存操作數(shù)只能有一個(gè),可以通過(guò)某個(gè)臨時(shí)寄存器達(dá)到類似目的。最簡(jiǎn)單的是忽略符號(hào)位的數(shù)據(jù)傳輸操作,386 和 AMD64 指令一樣,不同的 1、2、4 和 8 字節(jié)寬度有不同的指令:

Data Type 386/AMD64 Comment
[1]byte MOVB B => Byte
[2]byte MOVW W => Word
[4]byte MOVL L => Long
[8]byte MOVQ Q => Quadword

MOV 指令它不僅僅用于在寄存器和內(nèi)存之間傳輸數(shù)據(jù),而且還可以用于處理數(shù)據(jù)的擴(kuò)展和截?cái)嗖僮?。?dāng)數(shù)據(jù)寬度和寄存器的寬度不同又需要處理符號(hào)位時(shí),386 和 AMD64 有各自不同的指令:

Data Type 386 AMD64 Comment
int8 MOVBLSX MOVBQSX sign extend
uint8 MOVBLZX MOVBQZX zero extend
int16 MOVWLSX MOVWQSX sign extend
uint16 MOVWLZX MOVWQZX zero extend

比如當(dāng)需要將一個(gè) int64 類型的數(shù)據(jù)轉(zhuǎn)為 bool 類型時(shí),則需要使用 MOVBQZX 指令處理。

基礎(chǔ)算術(shù)指令有 ADD、SUBMULDIV 等指令。其中 ADDSUB、MUL、DIV 用于加、減、乘、除運(yùn)算,最終結(jié)果存入目標(biāo)寄存器?;A(chǔ)的邏輯運(yùn)算指令有 AND、OR 和 NOT 等幾個(gè)指令,對(duì)應(yīng)邏輯與、或和取反等幾個(gè)指令。

名稱 解釋
ADD 加法
SUB 減法
MUL 乘法
DIV 除法
AND 邏輯與
OR 邏輯或
NOT 邏輯取反

其中算術(shù)和邏輯指令是順序編程的基礎(chǔ)。通過(guò)邏輯比較影響狀態(tài)寄存器,再結(jié)合有條件跳轉(zhuǎn)指令就可以實(shí)現(xiàn)更復(fù)雜的分支或循環(huán)結(jié)構(gòu)。需要注意的是 MUL 和 DIV 等乘除法指令可能隱含使用了某些寄存器,指令細(xì)節(jié)請(qǐng)查閱相關(guān)手冊(cè)。

控制流指令有 CMP、JMP-if-x、JMP、CALLRET 等指令。CMP 指令用于兩個(gè)操作數(shù)做減法,根據(jù)比較結(jié)果設(shè)置狀態(tài)寄存器的符號(hào)位和零位,可以用于有條件跳轉(zhuǎn)的跳轉(zhuǎn)條件。JMP-if-x 是一組有條件跳轉(zhuǎn)指令,常用的有 JLJLZ、JE、JNE、JG、JGE 等指令,對(duì)應(yīng)小于、小于等于、等于、不等于、大于和大于等于等條件時(shí)跳轉(zhuǎn)。JMP 指令則對(duì)應(yīng)無(wú)條件跳轉(zhuǎn),將要跳轉(zhuǎn)的地址設(shè)置到 IP 指令寄存器就實(shí)現(xiàn)了跳轉(zhuǎn)。而 CALL 和 RET 指令分別為調(diào)用函數(shù)和函數(shù)返回指令。

名稱 解釋
JMP 無(wú)條件跳轉(zhuǎn)
JMP-if-x 有條件跳轉(zhuǎn),JLJLZ、JEJNE、JG、JGE
CALL 調(diào)用函數(shù)
RET 函數(shù)返回

無(wú)條件和有條件調(diào)整指令是實(shí)現(xiàn)分支和循環(huán)控制流的基礎(chǔ)指令。理論上,我們也可以通過(guò)跳轉(zhuǎn)指令實(shí)現(xiàn)函數(shù)的調(diào)用和返回功能。不過(guò)因?yàn)槟壳昂瘮?shù)已經(jīng)是現(xiàn)代計(jì)算機(jī)中的一個(gè)最基礎(chǔ)的抽象,因此大部分的 CPU 都針對(duì)函數(shù)的調(diào)用和返回提供了專有的指令和寄存器。

其它比較重要的指令有 LEA、PUSH、POP 等幾個(gè)。其中 LEA 指令將標(biāo)準(zhǔn)參數(shù)格式中的內(nèi)存地址加載到寄存器(而不是加載內(nèi)存位置的內(nèi)容)。PUSH 和 POP 分別是壓棧和出棧指令,通用寄存器中的 SP 為棧指針,棧是向低地址方向增長(zhǎng)的。

名稱 解釋
LEA 取地址
PUSH 壓棧
POP 出棧

當(dāng)需要通過(guò)間接索引的方式訪問(wèn)數(shù)組或結(jié)構(gòu)體等某些成員對(duì)應(yīng)的內(nèi)存時(shí),可以用 LEA 指令先對(duì)目前內(nèi)存取地址,然后在操作對(duì)應(yīng)內(nèi)存的數(shù)據(jù)。而棧指令則可以用于函數(shù)調(diào)整自己的棧空間大小。

最后需要說(shuō)明的是,Go 匯編語(yǔ)言可能并沒(méi)有支持全部的 CPU 指令。如果遇到?jīng)]有支持的 CPU 指令,可以通過(guò) Go 匯編語(yǔ)言提供的 BYTE 命令將真實(shí)的 CPU 指令對(duì)應(yīng)的機(jī)器碼填充到對(duì)應(yīng)的位置。完整的 X86 指令在 https://github.com/golang/arch/blob/master/x86/x86.csv 文件定義。同時(shí) Go 匯編還正對(duì)一些指令定義了別名,具體可以參考這里 https://golang.org/src/cmd/internal/obj/x86/anames.go。



以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)