//quick inline asm statements performing the swap_byte for key_scheduling
inline void swap_byte(unsigned char *x, unsigned char *y)
{
unsigned char t;
asm("movl %1, %%eax;"
"movl %%eax, %0;"
:"=r"(t)
:"r"(*x)
:"%eax");
asm("movl %1, %%eax;"
"movl %%eax, %0;"
:"=r"(*x)
:"r"(*y)
:"%eax");
asm("movl %1, %%eax;"
"movl %%eax, %0;"
:"=r"(*y)
:"r"(t)
:"%eax");
}
在这里,我尝试将x
中的字符交换为y
,并将y
添加到x
。
我通过将movl
更改为mov
来编译这些说明,但没有成功。编译/链接的问题在哪里?
以下是cygwin中编译的输出:
$ gcc rc4_main.c -o rc4ex
/tmp/ccy0wo6H.s: Assembler messages:
/tmp/ccy0wo6H.s:18: Error: operand type mismatch for `mov'
/tmp/ccy0wo6H.s:18: Error: operand type mismatch for `mov'
/tmp/ccy0wo6H.s:26: Error: operand type mismatch for `mov'
/tmp/ccy0wo6H.s:26: Error: operand type mismatch for `mov'
/tmp/ccy0wo6H.s:34: Error: operand type mismatch for `mov'
/tmp/ccy0wo6H.s:34: Error: operand type mismatch for `mov'
答案 0 :(得分:6)
为了简化它(比用户35443):
asm("" : "=r" (*x), "=r" (*y) : "1" (*x), "0" (*y));
看吧!没有代码!是的,这确实有效。
解释这是如何工作的:
当编译器构建代码时,它会跟踪每个寄存器中的值。所以,如果有这些输入到asm:
“r”(* x),“r”(* y)
编译器将选择一个寄存器并将* x放入其中,然后选择一个寄存器并将* y放入其中,然后调用您的asm。但它也跟踪哪个变量在哪个寄存器中。如果只是某种方式告诉编译器所有它必须做的就是开始将两个寄存器视为相反的变量,那么我们将被设置。这就是这段代码的作用:
因此,在不使用任何实际汇编指令的情况下,我们告诉编译器交换这两个值。
我们不会“免费”得到这个,因为编译器必须在调用asm之前将值加载到寄存器中。但是,无论如何都要发生......
实际更新内存怎么样?编译器将(如有必要)将寄存器中的这些值写回内存。因为它知道哪个变量在哪个寄存器中,所有变量都按预期工作。
答案 1 :(得分:1)
unsigned char t;
asm("movl %1, %%eax;"
"movl %%eax, %0;"
:"=r"(t) /* <--here */
:"r"(*x) /* <-- and here */
:"%eax");
您无法将值从32位寄存器移动到单字节存储单元。 t
位于堆栈中,x
位于其他位置,但两者都以相同的方式访问。其他方面的问题类似。你应该只移动一个字节。
尝试类似这样的事情,但有更多方法可以做到(我还没试过,请阅读下文):
unsigned char t;
asm("movb %1, %%al\n"
"movb %%al, %0\n"
:"=r"(t)
:"r"(*x)
:"%al");
asm("movb %1, %%al\n"
"movb %%al, %0\n"
:"=r"(*x)
:"r"(*y)
:"%al");
asm("movb %1, %%al\n"
"movb %%al, %0\n"
:"=r"(*y)
:"r"(t)
:"%al");
整个过程可以简化为:
asm("movb (%1), %%al\n"
"movb (%2), %%ah\n"
"movb %%ah, (%1)\n"
"movb %%al, (%2)\n"
: /* no outputs for compiler to know about */
: "r" (x), "r" (y)
: "%ax", "memory");