亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

通過匯編看golang函數(shù)的多返回值問題

 更新時(shí)間:2020年06月22日 09:42:42   作者:Go語(yǔ)言中文網(wǎng)  
這篇文章主要介紹了通過匯編看golang函數(shù)的多返回值問題,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

golang這門語(yǔ)言,有個(gè)比較好的特性,就是支持函數(shù)的多返回值。想C,C++,Java等這些語(yǔ)言,是不支持函數(shù)多返回的。但是C,C++可以使用傳遞指針,實(shí)現(xiàn)函數(shù)多返回。但是,你有沒有想過,golang是怎樣實(shí)現(xiàn)函數(shù)多返回值的呢?

我們知道,C,C++是通過寄存器實(shí)現(xiàn)函數(shù)返回值的,也就是先把返回值寫入到一個(gè)寄存器中,然后再?gòu)募拇嫫髦?,讀到函數(shù)的返回值。golang也是這樣實(shí)現(xiàn)的嗎?

偉大的思想家孔子曾說(shuō)過,在源碼面前一切都如同裸奔。后來(lái),魯迅先生,總結(jié)了孔子的思想,說(shuō)出了,在匯編面前,一切語(yǔ)法都是紙老虎。

下面我們通過golang的匯編指令,來(lái)看一下golang是怎樣實(shí)現(xiàn)函數(shù)的多返回值的

在看匯編之前,我們先用go的 debug 函數(shù)看下函數(shù)的棧信息

代碼很簡(jiǎn)單,不用解釋了

package main
import (
 "fmt"
 "runtime/debug"
)

func main() {
 one(3)
}

func one(a int) (int, int) {
 fmt.Println(string(debug.Stack()))
 return a, a + 5
}

 

我標(biāo)紅的這一行,就是 one 函數(shù)的棧信息,第一個(gè)參數(shù) 0x3 很好理解,就是我們傳入的參數(shù) 3

, 但是后面這兩個(gè)是啥?還有,我明明只傳了一個(gè)參數(shù),為啥會(huì)傳入三個(gè)參數(shù)?

到這里,我也就不賣關(guān)子了,直接說(shuō)了,后面這兩個(gè)參數(shù),就是one函數(shù)返回值的地址,也就是說(shuō),one函數(shù)返回值地址不在one函數(shù)中,而是在調(diào)用one函數(shù)的mian函數(shù)中。golang的函數(shù)返回值,和C,C++的不同,golang的返回值是通過棧內(nèi)地址實(shí)現(xiàn)的(返回值的地址是由函數(shù)調(diào)用者提供)。

package main

func main() {
 var b, c *int
 one(3, b, c)
}

func one(a int, b, c *int) {
}

也就是說(shuō),剛開始的那段代碼,和這段在功能實(shí)現(xiàn)上,沒有什么差別,只是golang編譯器提供的一個(gè)語(yǔ)法糖。

下面通過匯編來(lái)看一下

這次我們不是對(duì)深入分析golang的匯編,只是從匯編層面,驗(yàn)證我們之前結(jié)論(golang函數(shù)多返回問題)

所以,不會(huì)死磕plan9匯編語(yǔ)法,說(shuō)實(shí)話,plan9的很多知識(shí)我也不懂,大學(xué)沒開過匯編的課程,這些東西都是因?yàn)榕d趣自學(xué)的。

golang用的是plan9匯編,看plan9之前,先了解一下plan9的幾個(gè)概念

go匯編中有4個(gè)偽寄存器

  • FP: Frame pointer,指向棧底位置,一般用來(lái)引用函數(shù)的輸入?yún)?shù),用來(lái)訪問函數(shù)的參數(shù)
  • PC: Program counter: 程序計(jì)數(shù)器,用于分支和跳轉(zhuǎn)
  • SB: Static base pointer: 一般用于聲明函數(shù)或者全局變量
  • SP: Stack pointer:指向當(dāng)前棧幀的局部變量的開始位置(棧頂位置),一般用來(lái)引用函數(shù)的局部變量

我們用這段代碼進(jìn)行匯編

package main

func main() {
 one(3)
}

func one(a int) (int, int) {
 return a, a + 5
}

使用 go tool compile -N -l -S main.go 得到匯編代碼

"".main STEXT nosplit size=2 args=0x0 locals=0x0
  0x0000 00000 (C:\Users\bruce\Desktop\go\main.go:3)  TEXT "".main(SB), NOSPLIT|ABIInternal, $0-0
  0x0000 00000 (C:\Users\bruce\Desktop\go\main.go:3)  FUNCDATA  $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
  0x0000 00000 (C:\Users\bruce\Desktop\go\main.go:3)  FUNCDATA  $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
  0x0000 00000 (C:\Users\bruce\Desktop\go\main.go:3)  FUNCDATA  $3, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
  0x0000 00000 (C:\Users\bruce\Desktop\go\main.go:4)  PCDATA $2, $0
  0x0000 00000 (C:\Users\bruce\Desktop\go\main.go:4)  PCDATA $0, $0
  0x0000 00000 (C:\Users\bruce\Desktop\go\main.go:4)  XCHGL AX, AX
  0x0001 00001 (<unknown line number>) RET
  0x0000 90 c3           ..
"".one STEXT nosplit size=20 args=0x18 locals=0x0
  0x0000 00000 (C:\Users\bruce\Desktop\go\main.go:7)  TEXT "".one(SB), NOSPLIT|ABIInternal, $0-24
  0x0000 00000 (C:\Users\bruce\Desktop\go\main.go:7)  FUNCDATA  $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
  0x0000 00000 (C:\Users\bruce\Desktop\go\main.go:7)  FUNCDATA  $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
  0x0000 00000 (C:\Users\bruce\Desktop\go\main.go:7)  FUNCDATA  $3, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
  0x0000 00000 (C:\Users\bruce\Desktop\go\main.go:8)  PCDATA $2, $0
  0x0000 00000 (C:\Users\bruce\Desktop\go\main.go:8)  PCDATA $0, $0
  0x0000 00000 (C:\Users\bruce\Desktop\go\main.go:8)  MOVQ "".a+8(SP), AX
  0x0005 00005 (C:\Users\bruce\Desktop\go\main.go:8)  MOVQ AX, "".~r1+16(SP)
  0x000a 00010 (C:\Users\bruce\Desktop\go\main.go:8)  ADDQ $5, AX
  0x000e 00014 (C:\Users\bruce\Desktop\go\main.go:8)  MOVQ AX, "".~r2+24(SP)
  0x0013 00019 (C:\Users\bruce\Desktop\go\main.go:8)  RET
  0x0000 48 8b 44 24 08 48 89 44 24 10 48 83 c0 05 48 89 H.D$.H.D$.H...H.
  0x0010 44 24 18 c3          D$..

我只截取了和main,one函數(shù)相關(guān)的部分

TEXT "".one(SB), NOSPLIT|ABIInternal, $0-24 這行最后, $0-24 的含義,0代表one函數(shù)的棧幀大小(局部變量+可能需要的額外調(diào)用函數(shù)的參數(shù)空間的總大小),因?yàn)閛ne函數(shù)中沒有額外開銷,所有大小是0,24是傳入?yún)?shù)和返回值的大小,單位是字節(jié)。傳入的參數(shù)和返回值都是 int ,在64位機(jī)器上,大小是8個(gè)字節(jié),64位。

簡(jiǎn)單畫一下棧的示意圖

看一下這句 0x0000 00000 (C:\Users\bruce\Desktop\go\main.go:8) MOVQ "".a+8(SP), AX

SP寄存器指向的是棧頂?shù)奈恢茫?AX 是一個(gè)通用寄存器

MOVQ指令 把 參數(shù)a 也就是(SP+8)的值搬到AX中

0x0005 00005 (C:\Users\bruce\Desktop\go\main.go:8) MOVQ AX, "".~r1+16(SP)
同樣,把AX中的值搬到r1(返回值b)

0x000a 00010 (C:\Users\bruce\Desktop\go\main.go:8) ADDQ $5, AX
ADDQ 指令把AX值+5

0x000e 00014 (C:\Users\bruce\Desktop\go\main.go:8) MOVQ AX, "".~r2+24(SP)
最后把AX的值搬到r2(返回值c)

0x0013 00019 (C:\Users\bruce\Desktop\go\main.go:8) RET
最后RET指令,one函數(shù)結(jié)束

總結(jié)

通過對(duì)golang進(jìn)行匯編,真實(shí)了之前的結(jié)論

golang函數(shù)的多返回值不是通過寄存器傳遞,使用過使用調(diào)用值提供的地址,賦值實(shí)現(xiàn)的

先寫這些吧,我也是剛接觸golang的匯編,文中如有不正確的地方,還請(qǐng)指出

到此這篇關(guān)于通過匯編看golang函數(shù)的多返回值的文章就介紹到這了,更多相關(guān)匯編golang函數(shù)多返回值內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 匯編語(yǔ)言之寄存器(詳細(xì)介紹)

    匯編語(yǔ)言之寄存器(詳細(xì)介紹)

    這篇文章主要介紹了匯編語(yǔ)言之寄存器(詳細(xì)介紹),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2020-01-01
  • DEBUG 命令詳解

    DEBUG 命令詳解

    這篇文章主要介紹了DEBUG 命令詳解,需要的朋友可以參考下
    2006-12-12
  • VScode配置8086匯編環(huán)境的過程解析

    VScode配置8086匯編環(huán)境的過程解析

    這篇文章主要介紹了VScode配置8086匯編環(huán)境的過程解析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • asm基礎(chǔ)——匯編指令之in/out指令

    asm基礎(chǔ)——匯編指令之in/out指令

    這篇文章主要介紹了asm基礎(chǔ)——匯編指令之in/out指令,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • 匯編分析 Golang 循環(huán)(推薦)

    匯編分析 Golang 循環(huán)(推薦)

    循環(huán)是編程中很強(qiáng)大的一個(gè)概念,而且非常容易處理。這篇文章主要介紹了匯編分析 Golang 循環(huán),需要的朋友可以參考下
    2020-02-02
  • 計(jì)算機(jī)系統(tǒng)匯編語(yǔ)言和機(jī)器語(yǔ)言深入理解

    計(jì)算機(jī)系統(tǒng)匯編語(yǔ)言和機(jī)器語(yǔ)言深入理解

    這篇文章主要為大家介紹了計(jì)算機(jī)系統(tǒng)匯編語(yǔ)言和機(jī)器語(yǔ)言深入理解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 匯編程序成績(jī)排序的實(shí)現(xiàn)

    匯編程序成績(jī)排序的實(shí)現(xiàn)

    這篇文章主要介紹了匯編程序成績(jī)排序的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • 匯編語(yǔ)言指令集之條件轉(zhuǎn)移指令實(shí)現(xiàn)

    匯編語(yǔ)言指令集之條件轉(zhuǎn)移指令實(shí)現(xiàn)

    這篇文章主要介紹了匯編語(yǔ)言指令集之條件轉(zhuǎn)移指令實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • 什么是匯編語(yǔ)言

    什么是匯編語(yǔ)言

    匯編語(yǔ)言(assembly language)是一種用于電子計(jì)算機(jī)、微處理器、微控制器或其他可編程器件的低級(jí)語(yǔ)言,亦稱為符號(hào)語(yǔ)言
    2020-01-01
  • 匯編語(yǔ)言中debug命令使用小結(jié)

    匯編語(yǔ)言中debug命令使用小結(jié)

    Debug是DOS、Windows都提供的實(shí)模式(8086方式)程序的調(diào)試工具,本文主要介紹了匯編語(yǔ)言中debug命令使用小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03

最新評(píng)論