我正在尝试做一些代码优化来消除分支,原始的c代码是
if( a < b )
k = (k<<1) + 1;
else
k = (k<<1)
mov a, %rax
mov b, %rbx
mov k, %rcx
xor %rdx %rdx
shl 1, %rcx
cmp %rax, %rax
setb %rdx
add %rdx,%rcx
mov %rcx, k
#define next(a, b, k)\
__asm__("shl $0x1, %0; \
xor %%rbx, %%rbx; \
cmp %1, %2; \
setb %%rbx; \
addl %%rbx,%0;":"+c"(k) :"g"(a),"g"(b))
当我编译下面的代码时,我得到了错误:
operand type mismatch for `add'
operand type mismatch for `setb'
我该怎么修好它?
以下是您的代码中的错误:
SETB%bl
工作,而SETB%rbx
不工作。t=(A
应转换为
cmp B,A;AT&T x86汇编程序语法中的setb t
。要CMP的两个操作数的顺序不对。记住CMP的工作方式如下:
一旦您意识到前两个错误消息是由汇编程序生成的,那么调试它们的诀窍就是查看由gcc生成的汇编程序代码。尝试
gcc$cflags-s t.c
并将t.s
中有问题的行与x86操作码引用进行比较。关注每条指令允许的操作数代码,您将很快看到问题所在。
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
static uint64_t next(uint64_t a, uint64_t b, uint64_t k)
{
uint64_t tmp;
__asm__("shl $0x1, %[k];"
"xor %%rcx, %%rcx;"
"cmp %[b], %[a];"
"setb %%cl;"
"addq %%rcx, %[k];"
: /* outputs */ [k] "+g" (k), [tmp] "=&c" (tmp)
: /* inputs */ [a] "r" (a), [b] "g" (b)
: /* clobbers */ "cc");
return k;
}
int main()
{
uint64_t t, t0, k;
k = next(1, 2, 0);
printf("%" PRId64 "\n", k);
scanf("%" SCNd64 "%" SCNd64, &t, &t0);
k = next(t, t0, k);
printf("%" PRId64 "\n", k);
return 0;
}
main()转换为:
<+0>: push %rbx
<+1>: xor %ebx,%ebx
<+3>: mov $0x4006c0,%edi
<+8>: mov $0x1,%bl
<+10>: xor %eax,%eax
<+12>: sub $0x10,%rsp
<+16>: shl %rax
<+19>: xor %rcx,%rcx
<+22>: cmp $0x2,%rbx
<+26>: setb %cl
<+29>: add %rcx,%rax
<+32>: mov %rax,%rbx
<+35>: mov %rax,%rsi
<+38>: xor %eax,%eax
<+40>: callq 0x400470 <printf@plt>
<+45>: lea 0x8(%rsp),%rdx
<+50>: mov %rsp,%rsi
<+53>: mov $0x4006c5,%edi
<+58>: xor %eax,%eax
<+60>: callq 0x4004a0 <__isoc99_scanf@plt>
<+65>: mov (%rsp),%rax
<+69>: mov %rbx,%rsi
<+72>: mov $0x4006c0,%edi
<+77>: shl %rsi
<+80>: xor %rcx,%rcx
<+83>: cmp 0x8(%rsp),%rax
<+88>: setb %cl
<+91>: add %rcx,%rsi
<+94>: xor %eax,%eax
<+96>: callq 0x400470 <printf@plt>
<+101>: add $0x10,%rsp
<+105>: xor %eax,%eax
<+107>: pop %rbx
<+108>: retq
您可以看到
next()
在每次printf()
调用之前被移动到RSI中的结果。
这里是一个虚拟的*z++=*x++**y++指令。请注意,x、y和z指针寄存器必须指定为输入/输出,因为asm会修改它们。 在第一个示例中,在输入操作数中列出和有什么意义?同一份文件指出: 特别是,如果不将输入操作数指定为输出操作数,就无法指定输入操作数被修改。
我在函数中有以下代码: 现在我不知道为什么这不起作用。Gcc说:“错误:'asm'操作数有不可能的约束”我一直在学习Gcc内联汇编教程,我认为这是将参数从c代码带到内联汇编块的正确方法。 我还使用了为32位x86构建的gcc交叉编译器。
我试着创建这个过程(作为一个系统),它需要两个参数,用户名和密码,并根据它们创建一个用户: 问题是,当我尝试执行此过程(作为一个系统)时,我遇到了以下错误: 错误报告:ORA-01031:权限不足ORA-06512:在第9行的“系统.过程\u创建\u客户端”处ORA-06512:在第1 01031行。00000-“权限不足”*原因:试图在没有适当权限的情况下更改当前用户名或密码。如果试图在没有必要
从CSV文件中存在的数十亿中找到最大值的程序。 错误:java.io.ioException:映射项中的类型不匹配:应为org.apache.hadoop.io.text,已收到org.apache.hadoop.mapred.maptask$mapoutputbuffer.collect(maptask.java:1072)在org.apache.hadoop.mapred.maptask$ne
尝试使用gcc:https://github.com/wolf9466/cpuminer-multi/blob/master/cryptonight_aesni.c编译此源文件时遇到此错误 “CRYPTONIGT_AESNI.c:162:4:错误:操作数约束不一致”
错误:java.io.ioException:错误值类:类org.apache.hadoop.io.text不是类org.apache.hadoop.mapred.ifile$writer.append(ifile.java:194)在org.apache.hadoop.mapred.task$combineoutputCollector.collect(task.java:1350)在org.a