英文:
Go, x64 assembly and CMOVLMI: Where is this opcode described?
问题
我正在阅读Go源代码,就像其他人一样,当我阅读fastrand()
函数时,它在我的机器上应该在asm_amd64.s
文件中,我遇到了这段代码:
XORL $0x88888eef, DX
CMOVLMI BX, DX
MOVL DX, m_fastrand(AX)
但是我无法理解CMOVLMI
应该做什么。搜索结果显示,只有Go似乎知道它的存在;我可以找到许多在AMD X86_64参考手册中定义的CMOVxx
操作码,而且Wikipedia页面上有很长一段关于条件移动指令的历史,但是这个指令在那个列表中找不到。
CMOVLMI
是在哪里定义的?它是Go内部汇编器特有的吗?
英文:
I was reading through the Go source code, as one does, and as I was reading the fastrand()
function, which for my machine would be in the asm_amd64.s
file, I came across this snippet:
XORL $0x88888eef, DX
CMOVLMI BX, DX
MOVL DX, m_fastrand(AX)
For the life of me, I cannot figure out what CMOVLMI
is supposed to be doing. A search for it reveals that only Go seems to know anything about it; I can find plenty of CMOVxx
opcodes defined in the AMD X86_64 reference, and the Wikipedia Page has a long history of conditional move instructions, but this doesn't appear anywhere on that list.
Where is CMOVLMI defined? Is it unique to Go's internal assembler?
答案1
得分: 5
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语法 Intel语法 读作
--------- ------------ ----
OS o 溢出设置
OC no 溢出清除
CS, LO b, c, nae 进位设置/低于
CC, HS nb, nc, ae 进位清除/高于或等于
EQ e, z 等于
NE ne, nz 不等于
LS be, na 低于或等于
HI nbe, a 高于
MI s 负数
PL ns 正数
PS p, pe 奇偶设置
PC np, po 奇偶清除
LT l, nge 小于
GE nl, ge 大于或等于
LE le, ng 小于或等于
GT nle, g 大于
对于像ARM那样借位的目标,助记符LO
和HS
被交换了。对于跳转指令,Intel语法变体被识别为替代助记符,以便简化过渡。但对于其他指令,情况并非如此。
此外,Go汇编器不通过为不同的寄存器大小赋予不同的名称来区分通用寄存器大小(除了为了与AH
、BH
、CH
和DH
的一致性而支持的AL
、BL
、CL
和DL
)。寄存器BX
可以引用任何bl
、bx
、ebx
和rbx
,具体取决于指令的操作数大小。
最后,操作数的顺序遵循AT&T约定,即源操作数在前,目标操作数在后。
因此,该指令对应于Intel指令
cmovs edx, ebx
为了比较不同的表示方式,Go工具链附带的objdump
实用程序支持-gnu
标志。这将以GNU语法和Plan 9语法的形式转储指令,便于进行比较。
英文:
The Go assemblers are derived from the Plan 9 assemblers with little changes. The design concept of the Plan 9 assemblers is that they were supposed to have common syntax and naming conventions across all architectures. While making assembly code more consistent within the framework of the Go toolchain, it can at time be very confusing to read such assembly code for people more familiar with conventional assemblers.
As for the instruction in question, CMOVLMI BX, DX
, specifically; it demonstrates some of the peculiar design choices of the Go assembler. The mnemonic CMOVLMI
has to be read like an ARM mnemonic where CMOV
is the operation, L
is the operand size (long word, 32 bit) and MI
is the condition on which it is executed (minus, i.e. sign flag set). The operand size follows the established DEC conventions where B
, W
, L
, Q
, and O
stand for byte, word, long word, quad word, and octa word respectively. The condition codes follow M68k conventions; here is a handy translation table:
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
The mnemonics LO
and HS
are swapped for targets where carry is the inverse of borrow, like ARM. For jump instructions, the Intel syntax variants are recognised as alternative mnemonics to ease the transition. This is however not the case for other instructions.
Additionally, the Go assembler does not distinguish general purpose register sizes by given the different register sizes different names (except for AL
, BL
, CL
, and DL
supported for consistency with AH
, BH
, CH
, and DH
). The register BX
can refer to any of bl
, bx
, ebx
, and rbx
depending on the instruction's operand size.
Lastly, operand ordering follows AT&T conventions, i.e. source, then destination.
The instruction thus corresponds to the Intel instruction
cmovs edx, ebx
To compare the different representations, the objdump
utility shipped with the Go toolchain supports a -gnu
flag. This dumps instructions in GNU syntax in addition to Plan 9 syntax, making it easy to compare the two.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论