Elf*_*erg 1 x86 assembly x86-64 go eflags
我正在阅读 Go 源代码,正如人们所做的那样,当我阅读该fastrand()
函数时(对于我的机器来说该函数将位于文件中asm_amd64.s
),我遇到了以下代码片段:
XORL $0x88888eef, DX
CMOVLMI BX, DX
MOVL DX, m_fastrand(AX)
Run Code Online (Sandbox Code Playgroud)
对于我的一生,我无法弄清楚CMOVLMI
应该做什么。对它的搜索表明,似乎只有 Go 知道它的任何事情;CMOVxx
我可以找到AMD X86_64 参考中定义的大量操作码,并且维基百科页面有条件移动指令的悠久历史,但这并没有出现在该列表中的任何位置。
CMOVLMI 在哪里定义的?它是 Go 内部汇编器所独有的吗?
Go 汇编程序源自Plan 9 汇编程序,几乎没有变化。Plan 9 汇编器的设计理念是它们应该在所有体系结构中具有通用的语法和命名约定。虽然使汇编代码在 Go 工具链的框架内更加一致,但对于更熟悉传统汇编器的人来说,阅读此类汇编代码有时会非常混乱。
至于有问题的指令,CMOVLMI BX, DX
具体而言;它展示了 Go 汇编器的一些独特的设计选择。助记符CMOVLMI
必须像 ARM 助记符一样读取,其中CMOV
是操作,L
是操作数大小(长字,32 位),MI
是执行它的条件(minus,即符号标志设置)。操作数大小遵循既定的 DEC 约定,其中B
、W
、L
、Q
和分别O
代表字节、字、长字、四字和八字。条件代码遵循 M68k 约定;这是一个方便的翻译表:
Go syntax Intel syntax read
--------- ------------ ----
OS o Overflow Set
OC no Overflow Clear
CS, LO b, c, nae Carry Set / LOwer
CC, HS nb, nc, ae Carry Clear / Higher or Same
EQ e, z EQual
NE ne, nz Not Equal
LS be, na Lower or Same
HI nbe, a Higher
MI s MInus
PL ns PLus
PS p, pe Parity Set
PC np, po Parity Clear
LT l, nge Less Than
GE nl, ge Greater or Equal
LE le, ng Less or Equal
GT nle, g Greater Than
Run Code Online (Sandbox Code Playgroud)
助记符LO
和HS
被交换为进位与借位相反的目标,例如 ARM。对于跳转指令,英特尔语法变体被识别为替代助记符以简化转换。然而,其他指令的情况并非如此。
此外,Go 汇编器不会通过为不同的寄存器大小提供不同的名称来区分通用寄存器大小(除了AL
、BL
、CL
和DL
支持与AH
、BH
、CH
和 保持一致DH
)。寄存器BX
可以引用bl
、bx
、ebx
、 和中的任何一个,rbx
具体取决于指令的操作数大小。
最后,操作数排序遵循 AT&T 约定,即源,然后是目的地。
因此该指令对应于 Intel 指令
cmovs edx, ebx
Run Code Online (Sandbox Code Playgroud)
为了比较不同的表示形式,objdump
Go 工具链附带的实用程序支持一个-gnu
标志。除了 Plan 9 语法之外,这还会转储 GNU 语法中的指令,从而可以轻松比较两者。