I want to use inline-assembly in a C program, without using constraints, since I don't want to have to explain that in my complex enough school paper. I'm attempting to xor some characters with a key. Here's the code:
#include <stdio.h>
char text[11] = {'H','e','l','l','o'};
int key = 42;
int e;
char z;
int main()
{
for (e=0; e<12; e++){
z = text[e];
asm volatile(
"movl $z, %ax;" \
"movl $key, %bx;" \
"xor $ax, %bx;" \
"movl $ax, %[z];");
printf("%c\n", z);
}
return 0;
}
but I keep getting:
main.c:11:13: error: undefined named operand ‘z’ "movl $key, %ax;" \
I tried adding static
in front of the variables, since it could be a compiler/linker optimization thing. I also tried adding __attribute__((used))
but none of it helped. I am using GNU GCC v7.1.1
Any help is appreciated, thanks.
If possible, avoid using inline assembly at all.
If inline assembly has to be used, use extended inline assembly if at all possible and declare correct operands and clobber lists. In your particular case, something like this would work:
#include <stdio.h>
char text[11] = {'H','e','l','l','o'};
int key = 42;
int e;
char z;
int main()
{
for (e=0; e<12; e++){
z = text[e];
asm (
"movzbl %0, %%eax;" \
"movl %1, %%ebx;" \
"xor %%ebx, %%eax;" \
"movb %%al, %0;"
: "+m"(z) : "m"(key) : "eax", "ebx");
printf("%c\n", z);
}
return 0;
}
Here, "+m"(z)
is an output operand whereas "m"(key)
is an input operand. "eax", "ebx"
is the clobber list indicating which registers your code overwrites. As all side effects of the asm
statement are made explicit through its output operands and clobbers, the volatile
keyword can be omitted to give greater flexibility to the compiler.
Note that unless key
, z
, and e
being global variables is a requirement, it is a good idea to make them into automatic variables and to use an additional r
or i
constraint for the input and output operands to give the compiler more flexibility with chosing where to keep the variables.
Also pay attention to the corrected operand sizes. key
is a 32 bit variable and z
is an 8 bit variable. Lastly, I've fixed you xor
instruction. You have accidentally switched the operands.
Note that the assembly code can be done better. A slightly more efficient way to render the code would be like this:
#include <stdio.h>
char text[11] = {'H','e','l','l','o'};
int key = 42;
int e;
char z;
int main()
{
for (e=0; e<12; e++){
z = text[e];
asm (
"xorb %b1, %0"
: "+m"(z) : "r"(key));
printf("%c\n", z);
}
return 0;
}
This delegates loading key
from memory to the C compiler, allowing it to make more informed choices on where to keep the variable. It might also be a good idea to make key
and z
into automatic variables, but I am unsure if this is allowed under some unnamed constraints you might have.