[英]Returning a 64-bit result from a 32-bit IMUL with inline assembly in GCC
[英]GCC fails to generate 32-bit code from a function with inline assembly
我尝试生成这样的32位代码:gcc -S -m32 BMPTransformer.c -o BMPTransformer.s
我正在使用Ubuntu 13.04。 有类似问题的人似乎通过安装libc6-dev-i386克服了他们的困难。 但是,这对我没用。
编译器抱怨:
BMPTransformer.c:243:6:错误:在重新加载'asm'BMPTransformer.c:243:6时错误:在'GENERAL_REGS'类中找不到寄存器:'asm'操作数有不可能的约束
代码原样:
216 static void ASM_reverse_image(BMPImage *image)
217 {
218 asm (
219 "movl $0, %%eax\n"
220
221 "cmpl %%eax, %1\n"
222 "jl end\n"
223
224 "row:\n"
225 "movl (%0, %%eax, 4), %%edx\n"
226 "decl %1\n"
227 "movl (%0, %1, 4), %%esi\n"
228 "movl %%esi, (%0,%%eax, 4)\n"
229 "incl %%eax\n"
230 "movl %%edx, (%0, %1, 4)\n"
231 "cmpl %%eax, %1\n"
232 "jg row\n"
233
234 "end:\n"
235
236 : : "r"(image->pixel_data), "r"(image->header.height): "%eax", "%edx", "%esi"
237 );
238 }
使用64位a,b,c寄存器的代码运行得很好。 但我需要一个32位版本。
该错误通常表示编译器已用完寄存器。 你发布的小片段不应该是这样的,事实上它对我来说很好。 你可能没有说出一些重要的细节。
无论如何,绝对没有理由以当前的形式在inline asm中写这个。 编译器可以轻松生成更好(和工作)的代码。 初步比较肯定应该是C.
旁注:当使用gcc inline asm时,一般的想法是尽可能多地为编译器留下可能性。 例如,您不需要任何寄存器,您可以使用通用约束。
将其编码为普通C:
static void ASM_reverse_image(BMPImage *image)
{
int *pixel_data = image->pixel_data;
int tmp;
size_t idx = 0, height = image->header.height;
for (idx = 0; idx < height; idx++) {
tmp = pixel_data[idx];
pixel_data[idx] = pixel_data[height - idx];
pixel_data[height - idx] = tmp;
}
}
或者,如果您使用的是C ++,只需:
for (idx = 0; idx < height; idx++)
std::swap(pixel_data[idx], pixel_data[height - idx]);
编辑:对于装配练习,这样做:
int tmp;
asm("row:
mov (%0), %2
xchg %2, (%0, %1, 4)
lea 4(%0), %0
dec %1
jns row"
: : "r"(image->pixel_data), "r"(image->header.height), "r"(tmp)
: "memory", "cc");
但这不是好代码 - 主要是因为这是一种“流式”处理类型,应该通过矢量单元完成。
在gcc内联汇编中始终是一个好主意,以避免请求特定的寄存器 。 让编译器选择。 这可能意味着您必须将一个或多个“伪变量”声明为汇编寄存器操作数(以获得“reg预留”)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.