Golang CAS操作汇编代码解读
由于Golang使用的是Plan9的汇编,所以在阅读本文章前最好大致浏览一下plan9方面知识,毕竟plan9和x86还是有些区别的,虽然不是太大。
正文
本文解读的CAS操作汇编代码为x64版本的(win10环境)
代码地址:GO根目录\src\runtime\internal\atomic\asm_amd64.s

打开文件,来到对应的代码区,可以看到上面注释里面相应的伪代码,本文就是对其和其下方的汇编代码作一个简单的解析。
按照从上至下的顺序:
第一行: TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0-17 。$0-17表示的意思是这个TEXT block运行的时候,需要开辟的栈帧大小是 0 ,而17 = 8 + 4 + 4 + 1 = sizeof(pointer of int32) + sizeof(int32) + sizeof(int32) + sizeof(bool) (返回值是 bool ,占据 1 个字节。)

第二、三、四行如上图所示,前面的MOVQ代表搬移的数据大小为8字节,MOVL是4字节,int32占4直接所以使用MOVL。关于mov指令:movb(8位)=》1字节、movw(16位)=》2字节、movl(32位)=》 4字节、movq(64位) =》8字节。
然后就是LOCK了,LOCK 并不是指令,而是一个指令的前缀 (instruction prefix),是用来修饰 CMPXCHGL CX,0(BX) 的。
再往下,CMPXCHGL 有两个操作数,CX 和 0(BX) ,0(BX) ,这里的,0(BX) 代表从BX寄存器中第0个位置作为目标地址,0代表的是offset,这里的0(BX)指的就是前面的 *val(MOVQ ptr+0(FP), BX)。
CMPXCHGL 指令做的事情,首先会把 destination operand(也就是 0(BX))里的值 和 AX 寄存器里存的值做比较,如果一样的话会把 CX 里边存的值保存到 0(BX) 这块地址里 (虽然这条指令里并没有出现 AX,但是还是用到了,汇编里还是有不少这样的情况)CMPXCHGL 最后的那个 L 应该表示的是操作长度是 32 bit ,从函数的定义来看 old 和 new 都是 int32 函数返回一个 Bool 占用 8bit ,SETEQ 会在 AX 和 CX 相等的时候把 1 写进 ret+16(FP) (否则写 0)。
总结
由于本人水平也不咋地,能看懂就看吧,我已经尽力让它展示得更直观了。


本文系作者 @孤独常伴 原创发布在 L0ne1y。未经许可,禁止转载。