- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在使用一个库(pulseaudio,src/pulsecore/svolume_mmx.c),它的代码类似于以下虚拟代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
int main(int argc, char *argv[]) {
int32_t x = 5;
int32_t *p_x = &x;
#if defined(__i386__)
int32_t tmp;
#elif defined(__amd64__)
int64_t tmp;
#endif
__asm__ __volatile__ (
" xor %1, %1 \n\t"
" movd (%q0, %1, 4), %%mm0 \n\t"
" emms \n\t"
: "+r" (p_x), "+r" (tmp)
);
printf("%"PRId32"\n", x);
return 0;
}
我正在尝试将其编译为 64 位 mac osx 上的 32 位库。当我正常编译它时,一切正常,但是当我使用 -arch 标志将它编译为所需的 32 位库时,会发生这种情况:
$ gcc -std=c99 -arch i386 -o main main.c
/var/folders/random_stuff_here.s:22:bad register name `%rcx, %edx,4)'
阅读gcc 的汇编输出后,问题出在movd 行。 %q0 寄存器被填充为 %rcx,这是一个 64 位寄存器。汇编程序正试图从中创建 32 位输出,但失败了。
我找不到太多关于 %q0 中“q”的含义的信息,但我最终找到了 different compiler 的文档(第 194 页)将 q 描述为“如果目标支持四字,则为操作数生成四字寄存器名称。否则,它会生成一个字寄存器名称。(例如,如果操作数 0 在寄存器“a”中,然后 %q0 在 x86_64 上产生 %rax 或在 x86 上产生 %eax。)”如果您使用 'q' 标志要求它,asm block 的代码生成似乎会输出 64 位寄存器,即使 -arch 标志正在指定 32 位输出。
除了 -arch i386 标志外,还使用 -m32 标志根本没有帮助。我怎样才能告诉 asm 代码生成器只对 %qx 符号使用 32 位寄存器?我宁愿给 gcc 额外的标志,而不是修改这个库的源代码。
最佳答案
看起来你的 gcc 不喜欢在寻址表达式中显式混合 %q
和 normal 寄存器,和/或评估 %q
到 64 位注册名,即使你明确地为 32 位编译(并且它不存在)。
但是,由于您在寻址表达式中(错误)匹配使用(非)指针数据类型,因此在您/您的库中使用特定的 __asm__
表达式是相当虚假的。您可以相对轻松地更正:
#include <stdint.h> // has [u]intptr_t and "sized types" [u]int(8|16|32|64)_t
...
int myintval = 0;
int tmp = 0;
__asm__("mov (%0, %1, 4), ..."
: : "r"((void*)(intptr_t)myintval), "r"((void*)(intptr_t)tmp));
即首先手动将数据类型强制为 [u]intptr_t
(与指针具有相同底层大小的整数类型,无论您是在 32 位还是 64 位平台上),然后是实际指针( void*
),将其传递给输入寄存器约束。
这确保编译器将您的整数变量分配给可用于寻址操作的寄存器;该代码将在 32 位和 64 位 x86 中正常工作,并且无需使用显式寄存器宽度说明符。
成本/缺点?那么,在 64 位中,如果您使用寄存器而不是仅仅使用它们来寻址,那么例如xor %...,%...
变成显式的 xorq %r...,%r...
(带有 REX 前缀),即使这不是严格要求的.如果您不能接受,请使用 #ifdef
/#else
创建 32 位和 64 位代码块。
附带说明一下,如果您不能/不想修改库源代码,那么请尝试获取不同的 gcc 版本(下载更新的 XCode)。我无法使用 gcc 3.4.5 和各种 4.[14567].x 重现您的问题,但手头没有任何 4.2.x。
关于c - %q 在内联汇编中与 -arch i386,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10964893/
我在使用的教程中遇到了这个不寻常的代码。 #if !(arch(x86_64) || arch(arm64)) func sqrt(a: CGFloat) -> CGFloat { return CG
我的应用程序需要 double 计算。根据我在谷歌上找到的内容,我应该添加一个标志“-arch sm_13”或“-arch sm_20”。 Q1:“-arch sm_13”和“-arch sm_20”
在从不同的规范文件构建一些 RPM 时,我收到了上述警告 Binaries arch (1) not matching the package arch (2). 代码和一切都给了我,我对 RPM 很
似乎 Microsoft Visual C++ 提供了可在两种名称格式下重新分发的 VC++ 运行时的等效副本。 VS2017: @ /cygdrive/c/Program Files (x86)/M
在 Kotlin 文件中,我有一个“未解析的引用:arch”。 import android.arch.lifecycle.Lifecycle import android.arch.lifecycl
目前,我们正在项目中使用LiveData、ViewModel 和Room。 我们正在使用 Java 8。 我们在build.gradle中使用以下内容 // ViewModel and LiveDat
我在 Macbook Pro 上的 VirtualBox 上运行 Ubuntu 14.04 64 位 MAC。我在 hello_kernel.c 中有以下内容,我想运行它。 #include #in
我创建了一个 github 操作来在推送时部署代码。 安装软件包时会导致此错误。 Run npm i --no-optional && cd client && npm i --no-optional
当我尝试在 Ubuntu 机器中启用 PPP 时,在 menuconfig 之后发生以下错误并尝试制作内核: $ sudo make make[1]: *** No rule to make targ
测试二进制 二进制没问题 npm WARN rollback 回滚 node-pre-gyp@0.12.0 失败(这可能是无害的): EPERM: operation not permitted, l
当我尝试在 Ubuntu 机器中启用 PPP 时,在 menuconfig 和尝试制作内核之后发生了以下错误: $ sudo make make[1]: *** No rule to make tar
我正在尝试安装Webpack但它不断地给我同样的警告,而且 webpack 仍然没有安装在我的项目中。这是我正在处理的一个现有项目。我尝试了很多命令,例如 npm install --no-optio
我在我的raspberry pi上安装python密码软件包时遇到了一些问题,特别是python版本3.9.8(与pyenv一起安装)。密码包是使用pacman(python-cryptography
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界. 这篇CFSDN的博客文章Arch Linux安装后的一些初始设置简介由作者收集整理,如果你对这篇
我尝试在 ubuntu 12.04(64 位)上构建 gcc 4.8 主干。 当我使用配置时 ../gcc-trunk/configure -v --with-pkgversion='ubuntu12
slock 与 xfce 一起安装。 当我点击右上角的“锁定屏幕”时,屏幕变黑。按任意键,屏幕会变红,但如何取消呢? slock中没有解锁的UI? 最佳答案 我发现它只是在等待密码。输入正确的密码,屏
我正在尝试在 Cygwin 中为 Android NDK 配置工具链。我用这个tutorial .当我运行以下命令时: ./make-standalone-toolchain.sh --platfor
我安装了 Arch Arm到 Rpi3 上,然后将 sysroot rsync 到安装在 Lenovo thinkpad 上的 x86_64 Arch Linux。 然后我安装了 arm-linux-
我正在研究 Linux 内核模块。它需要有一种方法可以将所有进程显示为分层树。我已经编写了一个递归方法来显示进程及其子进程。我还尝试通过检查每个进程与 init_task 的距离来将其格式化为树。但是
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
我是一名优秀的程序员,十分优秀!