Assembly Objdump是否在已编译程序集上将fsubrp交换为fsubp?

Assembly Objdump是否在已编译程序集上将fsubrp交换为fsubp?,assembly,mingw,masm,disassembly,x87,Assembly,Mingw,Masm,Disassembly,X87,我正在将Quake 2的内嵌Win32程序集移植到GAS。我首先获取内联程序集,然后将其放入自己的ASM文件中。修复了所有问题,然后开始移植到GAS。我确实知道src/dst在AT&T与Intel语法(包括用于某些数学运算的浮点寄存器)和其他一些小问题上是相反的,但是当我得到这个编译的好结果时,我注意到代码没有按预期工作。我用compare实用程序仔细地查看了几个小时,并阅读了组装手册,最后在GAS和MASM版本上尝试了“objdump-dwrC>out.txt”。我注意到的很奇怪 除MASM版

我正在将Quake 2的内嵌Win32程序集移植到GAS。我首先获取内联程序集,然后将其放入自己的ASM文件中。修复了所有问题,然后开始移植到GAS。我确实知道src/dst在AT&T与Intel语法(包括用于某些数学运算的浮点寄存器)和其他一些小问题上是相反的,但是当我得到这个编译的好结果时,我注意到代码没有按预期工作。我用compare实用程序仔细地查看了几个小时,并阅读了组装手册,最后在GAS和MASM版本上尝试了“objdump-dwrC>out.txt”。我注意到的很奇怪

除MASM版本中有一条“fsubp st(1),st(0)”线外,所有代码的生成看起来都是相同的,在气体中是“fsubrp st(1),st(0)”。这很奇怪,因为MASM和GAS中的实际汇编代码都使用fsubrp。将其更改为fsubp允许粒子绘制代码按预期工作

为什么会这样

采取的步骤: 使用比较实用程序逐行验证src/dst,阅读x87组装手册,包括教程和GCC ASM手册,了解任何怪癖

代码段: 原始MASM代码:

fsubrp st(1), st(0)
气体代码:

fsubrp %st(0), %st(1)
根据objdump的MASM代码:

fsubp %st(0), st(1)
fsubrp %st(0), st(1)
根据objdump的气体代码:

fsubp %st(0), st(1)
fsubrp %st(0), st(1)
预期成果:
我希望在MASM文件的objdump中生成subrp,而不是fsubp。

这是一个已知的gas错误,不幸的是无法修复;对于带有寄存器操作数的x87非交换浮点指令(如
fdiv
vs.
fdivr
),反转与非反转助记符是错误的。正如编译器所期望的那样,这个bug将一直存在

参见气体手册的章节;这种语法设计缺陷源于AT&T的UnixWare汇编程序,GAS选择复制这种语法以实现兼容性


它还影响AT&T模式下的
objdump

我发现了这一点。多亏了Peter Cordes,我在MASM和GAS版本上使用了-Mintel。正如他所说,操作码是错误的。出于某种原因,如果你有和fsubp,然后是和fsubrp,你必须反转它。一旦完成,它就会生成正确的操作码。不确定这是否是一个非常模糊的问题。

我知道这一点,但操作数已经交换(对不起,应该澄清这一点)。这条指令在ASM文件中声明为fsubrp时,在MASM中变成了fsubp。我必须在GAS中将其改为fsubp,代码才能正常工作。@Maraakate我不是指AT&t语法中通常的交换。我的意思是,有些指令没有交换它们的操作数,而应该交换它们。这就是问题所在。我对汇编还是个新手,这就是为什么我要从这个小项目开始,将一个函数从一个移植到另一个。。。但是,是的,我已经看到GCC特别声明出于兼容性原因,一些FP数学需要交换操作数。我相信FSUB/FSUBP/FSUBRP就是其中之一。如果我以另一种方式编译它,编译器会警告它将交换它,因此%st(0)将首先出现。具体的问题是,FSUBRP是汇编代码中的内容,但objdump将其报告为FSUBP,我必须在GAS版本的代码中将其更改为FSUBP才能工作。@Maraakate和Fuz:这不是GAS“bug”,而是AT&t语法设计bug。GAS和objdump彼此兼容,并同意与英特尔文档不同,
fsubp%st(1)
de e1
。您可能希望使用GAS的
.intel_语法noprefix
/
objdump-Mintel
,因为该语法已经类似于MASM,并且不会出现AT&T语法错误。(我想我记得在过去的某个时候,看到objdump或gas在英特尔语法模式下应用at&T对助记符的解释,所以请检查您的工具版本。)@Maraakate:NASM在这里是一个有用的健全性检查;您可以使用NASM组装
fsubp st1
,并查看它是
de e9
,我们知道这是正确的。事实上,
objdump-drwC-Mintel
将其分解为
de e9 fsubp st(1),st
,这告诉我们,在英特尔语法模式下,2.31.1至少与英特尔一致,而不是与at&T一致。