Golang汇编命令解读

前端之家收集整理的这篇文章主要介绍了Golang汇编命令解读前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

http://www.cnblogs.com/yjf512/p/6132868.html


我们可以很容易将一个golang程序转变成汇编语言。

比如我写了一个main.go:

package main


func@H_403_15@ g@H_403_15@(p int)@H_403_15@@H_403_15@ int {
     return@H_403_15@ p+1@H_403_15@;
}

main@H_403_15@()@H_403_15@@H_403_15@ {
     c@H_403_15@ := g(4@H_403_15@) + 1@H_403_15@
     _@H_403_15@ = c@H_403_15@
}

使用命令:

GOOS=linux GOARCH=386@H_403_15@ go@H_403_15@ tool compile -S main.go@H_403_15@ >> main.S

我们就获取了main.S是main.go的汇编版本。

""@H_403_15@.g t=1@H_403_15@ size=16@H_403_15@ value=0@H_403_15@ args=0x10@H_403_15@ locals=0x0@H_403_15@
     0x0000@H_403_15@ 00000@H_403_15@ (main.go@H_403_15@:4@H_403_15@)     TEXT     ""@H_403_15@.g(SB),$0@H_403_15@-16@H_403_15@
     0x0000@H_403_15@ 00000@H_403_15@ (main.go@H_403_15@:4@H_403_15@)     NOP
     0x0000@H_403_15@ 00000@H_403_15@ (main.go@H_403_15@:4@H_403_15@)     FUNCDATA     $0@H_403_15@,gclocals·23e8278@H_403_15@e2b69a3a75fa59b23c49ed6ad(SB)
     0x0000@H_403_15@ 00000@H_403_15@ (main.go@H_403_15@:4@H_403_15@)     FUNCDATA     $1@H_403_15@,gclocals·33@H_403_15@cdeccccebe80329f1fdbee7f5874cb(SB)
     0x0000@H_403_15@ 00000@H_403_15@ (main.go@H_403_15@:5@H_403_15@)     MOVQ     ""@H_403_15@.p+8@H_403_15@(FP),BX
     0x0005@H_403_15@ 00005@H_403_15@ (main.go@H_403_15@:5@H_403_15@)     INCQ     BX
     0x0008@H_403_15@ 00008@H_403_15@ (main.go@H_403_15@:5@H_403_15@)     MOVQ     BX,""@H_403_15@.~r1+16@H_403_15@(FP)
     0x000d@H_403_15@ 00013@H_403_15@ (main.go@H_403_15@:5@H_403_15@)     RET
     0x0000@H_403_15@ 48@H_403_15@ 8@H_403_15@b 5@H_403_15@c 24@H_403_15@ 08@H_403_15@ 48@H_403_15@ ff c3 48@H_403_15@ 89@H_403_15@ 5@H_403_15@c 24@H_403_15@ 10@H_403_15@ c3        H.\$.H..H.\$..
""@H_403_15@.main t=1@H_403_15@ size=16@H_403_15@ value=0@H_403_15@ args=0x0@H_403_15@ locals=0x0@H_403_15@
     0x0000@H_403_15@ 00000@H_403_15@ (main.go@H_403_15@:8@H_403_15@)     TEXT     ""@H_403_15@.main(SB),$0@H_403_15@-0@H_403_15@
     0x0000@H_403_15@ 00000@H_403_15@ (main.go@H_403_15@:8@H_403_15@)     NOP
     0x0000@H_403_15@ 00000@H_403_15@ (main.go@H_403_15@:8@H_403_15@)     FUNCDATA     $0@H_403_15@,255)">go@H_403_15@:8@H_403_15@)     FUNCDATA     $1@H_403_15@,255)">go@H_403_15@:9@H_403_15@)     MOVQ     $4@H_403_15@,BX
     0x0007@H_403_15@ 00007@H_403_15@ (main.go@H_403_15@:9@H_403_15@)     INCQ     BX
     0x000a@H_403_15@ 00010@H_403_15@ (main.go@H_403_15@:9@H_403_15@)     INCQ     BX
     0x000d@H_403_15@ 00013@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     RET
     0x0000@H_403_15@ 48@H_403_15@ c7 c3 04@H_403_15@ 00@H_403_15@ 00@H_403_15@ 00@H_403_15@ 48@H_403_15@ ff c3 48@H_403_15@ ff c3 c3        H......H..H...
""@H_403_15@.init t=1@H_403_15@ size=80@H_403_15@ value=0@H_403_15@ args=0x0@H_403_15@ locals=0x0@H_403_15@
     0x0000@H_403_15@ 00000@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     TEXT     ""@H_403_15@.init(SB),255)">go@H_403_15@:11@H_403_15@)     MOVQ     (TLS),CX
     0x0009@H_403_15@ 00009@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     CMPQ     SP,16@H_403_15@(CX)
     0x000d@H_403_15@ 00013@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     JLS     62@H_403_15@
     0x000f@H_403_15@ 00015@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     NOP
     0x000f@H_403_15@ 00015@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     FUNCDATA     $0@H_403_15@,gclocals·33@H_403_15@cdeccccebe80329f1fdbee7f5874cb(SB)
     0x000f@H_403_15@ 00015@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     FUNCDATA     $1@H_403_15@,255)">go@H_403_15@:11@H_403_15@)     MOVBQZX     ""@H_403_15@.initdone·(SB),BX
     0x0016@H_403_15@ 00022@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     CMPB     BL,$0@H_403_15@
     0x0019@H_403_15@ 00025@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     JEQ     47@H_403_15@
     0x001b@H_403_15@ 00027@H_403_15@ (main.0x0022@H_403_15@ 00034@H_403_15@ (main.2@H_403_15@
     0x0025@H_403_15@ 00037@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     JNE     40@H_403_15@
     0x0027@H_403_15@ 00039@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     RET
     0x0028@H_403_15@ 00040@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     PCDATA     $0@H_403_15@,$0@H_403_15@
     0x0028@H_403_15@ 00040@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     CALL     runtime.throwinit(SB)
     0x002d@H_403_15@ 00045@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     UNDEF
     0x002f@H_403_15@ 00047@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     MOVB     $1@H_403_15@,21)">""@H_403_15@.initdone·(SB)
     0x0036@H_403_15@ 00054@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     MOVB     $2@H_403_15@,21)">""@H_403_15@.initdone·(SB)
     0x003d@H_403_15@ 00061@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     RET
     0x003e@H_403_15@ 00062@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     CALL     runtime.morestack_noctxt(SB)
     0x0043@H_403_15@ 00067@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     JMP     0@H_403_15@

首先这个程序根据TEXT是定义函数的,分为3个部分

0x0000@H_403_15@ 00000@H_403_15@ (main.go:4@H_403_15@)     TEXT     16@H_403_15@ 
0x0000@H_403_15@ 00000@H_403_15@ (main.go:8@H_403_15@)     TEXT     0@H_403_15@
0x0000@H_403_15@ 00000@H_403_15@ (main.go:11@H_403_15@)     TEXT     0@H_403_15@

这个"". 代表的是这个函数的命名空间。
g(SB) 这里就有个SB的伪寄存器。全名未Static Base,代表g这个函数地址,@H_403_15@ 0@H_403_15@−@H_403_15@16@H_403_15@中@H_403_15@@H_403_15@@H_403_15@@H_403_15@的@H_403_15@@H_403_15@@H_403_15@@H_403_15@@H_403_15@@H_403_15@@H_403_15@@H_403_15@@H_403_15@@H_403_15@ 0−16中的@H_403_15@@H_403_15@0代表局部变量字节数总和,0表示不存在局部变量。-16代表在0的地址基础上空出16的长度作为传入和返回对象。这个也就是golang如何实现函数的多返回值的方法了。它在定义函数的时候,开辟了一定空间存储传入和传出对象。

NOP命令是作为占位符使用,提供给编译器使用的。可以忽略不看。

下面是

0x0000@H_403_15@ 00000@H_403_15@ (main.go:4@H_403_15@)     FUNCDATA     $0,gclocals·23@H_403_15@e8278e2b69a3a75fa59b23c49ed6ad(SB)
     0x0000@H_403_15@ 00000@H_403_15@ (main.go:4@H_403_15@)     FUNCDATA     $1,gclocals·33@H_403_15@cdeccccebe80329f1fdbee7f5874cb(SB)

这里的FUNCDATA是golang编译器自带的指令,plan9和x86的指令集都是没有的。它用来给gc收集进行提示提示@H_403_15@ 0@H_403_15@和@H_403_15@@H_403_15@@H_403_15@@H_403_15@@H_403_15@@H_403_15@@H_403_15@@H_403_15@@H_403_15@@H_403_15@ 0和@H_403_15@@H_403_15@1是用于局部函数调用参数,需要进行回收。

下面是

0x0000@H_403_15@ 00000 (main@H_403_15@.go@H_403_15@:5)@H_403_15@     MOVQ@H_403_15@     "".p@H_403_15@+8(FP@H_403_15@),BX@H_403_15@
     0x0005@H_403_15@ 00005 (INCQ@H_403_15@     x0008@H_403_15@ 00008 (MOVQ@H_403_15@     BX@H_403_15@,"".~r1@H_403_15@+16(FP@H_403_15@)

这里有一个FP寄存器,FP是frame pointer,是指向栈底,SP是指向栈顶。BX是一个临时寄存器,那么上面的句子是代表把FP+8这个位置的数据(参数p),保存到BX中。FP+8代表什么呢,按照上面的图,代表的是参数

INCQ是自增算法,BX里面的数自加1,然后把BX里面的数存储到FP+16,代表的是返回值。
下面就是RET,直接返回。

下面再看看main,我们会发现,main函数里面并没有call g函数,这是由于go汇编编译器会把一些短的函数变成内嵌函数,减少函数调用

if

我们在main里面增加一个判断逻辑。代码为:

package main


c@H_403_15@ := g(4@H_403_15@) + 1@H_403_15@
     var@H_403_15@ d bool
     if@H_403_15@ (c@H_403_15@ > 4@H_403_15@) {
          d = true@H_403_15@
     } else@H_403_15@ {
          d = false@H_403_15@
     }
     _@H_403_15@ = d
     return@H_403_15@
}

对应的main的汇编为:

0x0000@H_403_15@ 00000@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     CMPQ     BX,$4@H_403_15@
     0x0011@H_403_15@ 00017@H_403_15@ (main.go@H_403_15@:11@H_403_15@)     JLE     27@H_403_15@
     0x0013@H_403_15@ 00019@H_403_15@ (main.go@H_403_15@:12@H_403_15@)     MOVQ     $1@H_403_15@,AX
     0x001a@H_403_15@ 00026@H_403_15@ (main.go@H_403_15@:17@H_403_15@)     RET
     0x001b@H_403_15@ 00027@H_403_15@ (main.go@H_403_15@:14@H_403_15@)     MOVQ     $0@H_403_15@,AX
     0x001d@H_403_15@ 00029@H_403_15@ (main.go@H_403_15@:17@H_403_15@)     JMP     26@H_403_15@

可以看是试用CMPQ来进行比较的,JLE代表CMP比较之后的结果,如果BX小于等于4,那么就跳到27指令,就是MOVQ $0,AX,把AX赋值为0,就是false,否则赋值为1,true

这里的JLE是条件转移指令:http://baike.baidu.com/link?url=pdfEpBZ-c-owW0YJrAL71MUi1nIlEpBqljD3agfLtB5KrAaFembK6yKKUNycaSUWTTTyynKhNIfw2LXvGFx4euTIgyXQcVLz5HPxS4AO-kVT9wQxlL6_O-1ygTwfshEgas91S14FU3CRU7a1jImTSK

for

程序改为:

package main


var@H_403_15@ sum int
     for@H_403_15@ i := 0@H_403_15@; i < p; i++ {
          sum = sum + i
     }
     return@H_403_15@ sum
}

c@H_403_15@
}

这里面有一个for循环,产生的汇编为:

0x0000@H_403_15@ 00000@H_403_15@ (main.go@H_403_15@:4@H_403_15@)     MOVQ     0x0005@H_403_15@ 00005@H_403_15@ (main.23e8278@H_403_15@e2b69a3a75fa59b23c49ed6ad(SB)
     0x0005@H_403_15@ 00005@H_403_15@ (main.33@H_403_15@cdeccccebe80329f1fdbee7f5874cb(SB)
     0x0005@H_403_15@ 00005@H_403_15@ (main.go@H_403_15@:5@H_403_15@)     MOVQ     $0@H_403_15@,CX
     0x0007@H_403_15@ 00007@H_403_15@ (main.go@H_403_15@:6@H_403_15@)     MOVQ     $0@H_403_15@,AX
     0x0009@H_403_15@ 00009@H_403_15@ (main.go@H_403_15@:6@H_403_15@)     CMPQ     AX,DX
     0x000c@H_403_15@ 00012@H_403_15@ (main.go@H_403_15@:6@H_403_15@)     JGE     $0@H_403_15@,25@H_403_15@
     0x000e@H_403_15@ 00014@H_403_15@ (main.go@H_403_15@:7@H_403_15@)     ADDQ     AX,CX
     0x0011@H_403_15@ 00017@H_403_15@ (main.go@H_403_15@:6@H_403_15@)     INCQ     AX
     0x0014@H_403_15@ 00020@H_403_15@ (main.go@H_403_15@:6@H_403_15@)     NOP
     0x0014@H_403_15@ 00020@H_403_15@ (main.0x0017@H_403_15@ 00023@H_403_15@ (main.go@H_403_15@:6@H_403_15@)     JLT     $0@H_403_15@,14@H_403_15@
     0x0019@H_403_15@ 00025@H_403_15@ (main.go@H_403_15@:9@H_403_15@)     MOVQ     CX,21)">""@H_403_15@.~r1+16@H_403_15@(FP)
     0x001e@H_403_15@ 00030@H_403_15@ (main.go@H_403_15@:9@H_403_15@)     RET

AX存的是变量i,DX存的是参数p,CX存的是变量sum,下面的几个命令:

0x0009@H_403_15@ 00009@H_403_15@ (main.14@H_403_15@

实际上是使用CMP,JGE,JLT来不断控制循环过程。 

猜你在找的Go相关文章