movl on x64 with GCC inline

Posted

技术标签:

【中文标题】movl on x64 with GCC inline【英文标题】: 【发布时间】:2014-04-21 09:56:22 【问题描述】:

在 x64 中,我想在给定 64 位地址的情况下从内存中读取 32 位值。这似乎相当琐碎,只需使用movl 指令即可。

但是,使用 GCC 内联“扩展”汇编程序,我无法完成这项工作。以下是我的代码:

unsigned row = 0;
__asm __volatile__ 
(
 "again:"

 "movzbq (%[px]), %%rax\n"
 "movzwq (%[symbols],%%rax,2), %%rax\n"
 "add %[table], %%rax\n"
 "movl (%%rax,%[row],4), %[row]\n" /* <------------ */
 "cmp %[row], %[match_limit]; jb end;\n"

 "inc %[px]\n"
 "cmp %[px_end], %[px]; jb again\n"

 "end:\n"
 : "=r" (row), "=r" (px)
 : [row] "0" (row),
   [px] "1" (px),
   [px_end] "r" (px_end),
   [symbols] "r" (char_to_symbol),
   [table] "r" (table),
   [match_limit] "r" (match_limit)
 : "%rax"
 );

这给了我“指令操作数无效”的错误消息。如果我将movl 更改为movslq,它会做我想做的事情(只要我的号码是31 位或更少)。换句话说,我想要的是movzlq 行为——除非它不存在,因为在 x64 中所有移动都将零扩展。

我对 GCC 的扩展内联语法非常陌生。我如何在这个位置获得movl

【问题讨论】:

这是 AT&T 语法 -- 目的地是 %[row],而不是 %rax 您似乎正试图从一个内存移动到另一个内存。 mov 无法做到这一点。 【参考方案1】:

您需要对(低位)32 位寄存器使用k 操作数修饰符,例如,

movl (%%rax,%0,4), %k0

我不确定在哪里可以找到这些的最终列表。在these 答案和this 教程中有一些。

【讨论】:

您链接到的 SO 问题的答案实际上仍然是正确的 AFAIK - 唯一的“规范”列表在 gcc 的架构定义文件中,raw.github.com/mirrors/gcc/trunk/gcc/config/i386/i386.md

以上是关于movl on x64 with GCC inline的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL 11 install with jit on CentOS 7.5 X64

gcc内嵌汇编

我的第一个汇编程序(X64,AT&T)

我的第一个汇编程序(X64,AT&T)

Mysql Innodb Deadlock on delete with Primary Keys IN 语句

[Javascript] Use JavaScript's for-in Loop on Objects with Prototypes