x86中未使用或使用最少的MOV指令,可用于自定义MOV扩展名

问题描述 投票:0回答:1

我正在用gem5模拟器在X86架构中对自定义MOV指令进行建模,以测试其在模拟器上的实现,我需要使用内联汇编来编译我的C代码以创建一个二进制文件。但是由于它是GCC编译器中尚未实现的自定义指令,因此编译器将抛出错误。我知道一种方法是扩展GCC编译器以接受我的自定义X86指令,但是我不想这样做,因为它比较耗时(但是以后会这样做)。

作为一个临时的技巧(只是检查我的实现是否值得)。我想在模拟器中更改其基础的“微操作”时编辑已经是MOV的指令,以欺骗GCC接受我的“自定义”指令并进行编译。

因为它们是x86体系结构中可用的许多类型的MOV指令。由于它们是86体系结构reference中的各种MOV指令。

因此,我的问题是,哪种MOV指令使用最少,我可以编辑其底层微操作。假设我的工作量仅包含整数,即很可能不会使用xmm和mmx寄存器,并且我的指令镜像了MOV指令的相同实现。

gcc x86 inline-assembly machine-code gem5
1个回答
1
投票
您最好的选择是常规mov,其前缀是GCC永远不会自己发出的。


[GCC不会解析其内联asm模板字符串,而是将其包含在其asm文本输出中,以在替换%number操作数之后将其提供给汇编器。因此,GCC本身并不是使用内联汇编发送任意汇编文本的障碍。

并且您可以使用.byte发出任意机器代码。

也许一个不错的选择是将0E字节用作特殊的mov编码的前缀,而您将要特别进行GEM解码。 0E is push CS in 32-bit mode,在64位模式下无效。 GCC永远也不会发射。

或者只是一个F2 0E前缀; GCC永远不会在push CS操作码(不适用的地方)前仅发出repne。 (F3repne/ mov在用于内存目标指令时表示xrelease,因此请勿使用。movs说F2 repne是与rep ed指令一起使用时的xacquire前缀,但不将repe包含到内存中,以便在那里被静默忽略。)

和往常一样,不适用的前缀没有记录的行为,但是实际上,不理解https://www.felixcloutier.com/x86/xacquire:xrelease / lock的CPU会忽略它。将来的某些CPU可能会理解它的特殊含义,而这正是您使用GEM所做的。

如果您想

防止在实际CPU上运行的版本中意外保留这些前缀,则选择mov而不是rep是更好的选择。> (它会在64位模式下#UD-> SIGILL,或者通常会因在32位模式下弄乱堆栈而崩溃。)但是,如果您do希望能够在实际环境中运行完全相同的二进制文件CPU,具有相同的代码对齐方式以及所有内容,因此理想的是忽略REP前缀。


在标准repne指令之前使用前缀的优点是让汇编程序为您编码操作数:

.byte 0x0e;

((多种替代约束使编译器可以选择reg / mem目标或reg / mem源。实际上,它更喜欢寄存器目标,即使这样做会使它花费另一条指令来进行自己的存储,也很糟。)

repne;,对于仅允许内存目标的版本:

mov

如果您希望此功能可用于加载,我认为您必须制作该函数的2个独立版本,并在适当的情况下手动使用加载版本或存储版本,因为GCC似乎想在任何时候使用reg,reg可以。


或者使用允许寄存器输出的版本(或另一个将结果作为template<class T> void fancymov(T& dst, T src) { // fixme: imm -> mem needs a size suffix, defeating template // unless you use Intel-syntax where the operand includes "dword ptr" asm("repne; movl %1, %0" #if 1 : "=m"(dst) : "ri" (src) #else : "=g,r"(dst) : "ri,rmi" (src) #endif : // no clobbers ); } void test(int *dst, long src) { fancymov(*dst, (int)src); fancymov(dst[1], 123); } 返回的版本,请参见Godbolt链接):

On the Godbolt compiler explorer

© www.soinside.com 2019 - 2024. All rights reserved.