Double Colon "::" operator in C/assembly - c

First off, no, I'm not talking about the C++ scope resolution operator.
I have the following syntax:
asm(
"mov R0,%0\n"
"mov R1,%1\n"
"mov R3,%2\n"
"mov R4,%3\n"
"mov R5,%4\n"
::"r"(<A_VALUE>),
"r"(<A_VALUE>),
"r"(<A_VALUE>),
"r"(<A_VALUE>),
"r"(<A_VALUE>),
:"r0","r1","r2"
)
What does colon and the double colon mean?
I do remember something having to do with string concatenation when dynamically creating variable names.
Million thanks in advance!

The :: isn't an operator, it's two : separators. See GCC Manual - Extended ASM for more details.
asm asm-qualifiers ( AssemblerTemplate
: OutputOperands
[ : InputOperands
[ : Clobbers ] ])
asm asm-qualifiers ( AssemblerTemplate
: OutputOperands
: InputOperands
: Clobbers
: GotoLabels)
In your case you have an empty OutputOperands parameter:
asm(
// Assembler Template
"mov R0,%0\n"
"mov R1,%1\n"
"mov R3,%2\n"
"mov R4,%3\n"
"mov R5,%4\n"
:
// OutputOperands
// (none)
:
// Input Operands
"r"(<A_VALUE>),
"r"(<A_VALUE>),
"r"(<A_VALUE>),
"r"(<A_VALUE>),
"r"(<A_VALUE>),
:
// Clobbers
"r0","r1","r2"
)

Related

C Inline Assembly Unordered?

In C I have:
__asm__ (
"mov $0x2,%rax;"
"mov $0x6000dd,%rdi;"
"mov $0x0,%rsi;"
"syscall;"
);
But when I comppile it in the assembly file I see:
# 12 "mine.cxx" 1
mov $0x2,%rax;mov $0x6000dd,%rdi;mov $0x0,%rsi;syscall;
why they are in 1 line like this
How to separate them?
You should add \n to separate lines.
__asm__ (
"mov $0x2,%rax;\n"
"mov $0x6000dd,%rdi;\n"
"mov $0x0,%rsi;\n"
"syscall;\n"
);
Adding \n will be helpful for you.
__asm__ (
"mov $0x2,%rax;\n"
"mov $0x6000dd,%rdi;\n"
"mov $0x0,%rsi;\n"
"syscall;\n"
);

Error : operand type mismatch for 'mov', 'out'

everyone.
I am trying to use the inline assembly technique in c programs.
But, An error : operand type mismatch for 'mov', 'out' occurs when compiling.
My code
#define updateCursor(X, Y)({
__asm__ volatile(
"mov %%al, $0x0f \n\t"
"mov %%dx, $0x03d4 \n\t"
"out %%dx, %%al \n\t"
"mov %%al, %[x] \n\t" // No-Error
"mov %%dx, $0x03d5 \n\t"
"out %%dx, %%al \n\t"
:: (x) "m" (X)
: "al", "dx");
})
I do not understand why I get an error on almost every line. (except for the no-error part)
I am very grateful if you help me with what is wrong and how to fix it.

Merging together inline assembly snippets

So, I have this code that works as expected:
#include <stdio.h>
int main () {
unsigned int i;
int x=5;
__asm__ ("movl %1, %0;"
"subl %2, %0;"
: "=r" (i)
: "r" (4), "r" (x)
: "0");
__asm__ ("movl %1, %0;"
: "=r" (x)
: "r" (i)
: "0");
printf("%d\n", x);
return 0;
}
How do I merge the two calls into one?
The first __asm__ sets: i <- 4 - x. The second sets: x <- i. They can be combined as:
__asm__ ("subl %k2, %k0" : "=r" (x) : "0" ((unsigned)(4)), "g" (x));
No clobbers are needed (unless you want to include "cc", which is always assumed by gcc anyway), and there's no issue of inputs being overwritten before they are read. The "g" constraint indicates that a register, memory, or immediate operand is acceptable. The output should be: "-1" in this case: x <- 4 - 5
Note: the first __asm__ should have =&r for its output. Furthermore, neither should list %0 as clobbered - this is implicit, as %0 is an output in both cases.
Those are nonsensical asm blocks to start with. Rule of thumb is, if you ever use a mov you are probably doing it wrong. Also, even though you claimed it works as expected, the code is broken. Nothing stops the compiler from allocating %2 to the same register as %0 producing wrong code. You were just lucky it didn't happen for you.
Anyway, the second asm block simply copies i into x. As such a merged asm could look like:
__asm__ ("movl %2, %0;"
"subl %3, %0;"
"movl %0, %1;"
: "=&r" (i), "=r" (x)
: "r" (4), "r" (x));
This is of course still silly, but at least it isn't technically wrong. Notice the early-clobber & modifier for the first output. It isn't needed for the second, however.

Inline assembly in C not working properly

I'm trying to learn how to use inline assembly in C code.
I have created a small program that should add two integers:
int main(){
int a=1;
int b=2;
asm( "movl %0, %%r8d;"
"movl %1, %%r9d;"
"addl %%r8d, %%r9d;"
"movl %%r9d, %1;"
: "=r" (a)
: "r" (b)
:"%r8","%r9" );
printf("a=%d\n",a);
return 0;
}
The aim was to load a and b into the registers %r8 and %r9, add them, and then put the output back in a.
However this program prints a=2 instead a=3. I'm not sure if the problem is in the inline technique or in the assembly itself.
There are two issues here:
First: The "=r" constraint you use for the output operand a indicates to the compiler that the operand is write-only — it is allowed to assume that the initial value is not needed. This is definitely not the case for your code! Change the qualifier to "+r" to let the compiler know that the initial value is important.
Second: You are moving the result to the wrong register! The target %1 of the last movl is the register corresponding to b, not a. You want %0.
Fixed:
asm(
"movl %0, %%r8d;"
"movl %1, %%r9d;"
"addl %%r8d, %%r9d;"
"movl %%r9d, %0;"
: "+r" (a)
: "r" (b)
: "%r8", "%r9"
);

SSE2 instruction in C code

I am trying to reverse engineer a c code, but this part of assembly I cant really understand. I know it is part of the SSE extension. However, somethings are really different than what I am used to in x86 instructions.
static int sad16_sse2(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)
{
int ret;
__asm__ volatile(
"pxor %%xmm6, %%xmm6 \n\t"
ASMALIGN(4)
"1: \n\t"
"movdqu (%1), %%xmm0 \n\t"
"movdqu (%1, %3), %%xmm1 \n\t"
"psadbw (%2), %%xmm0 \n\t"
"psadbw (%2, %3), %%xmm1 \n\t"
"paddw %%xmm0, %%xmm6 \n\t"
"paddw %%xmm1, %%xmm6 \n\t"
"lea (%1,%3,2), %1 \n\t"
"lea (%2,%3,2), %2 \n\t"
"sub $2, %0 \n\t"
" jg 1b \n\t"
: "+r" (h), "+r" (blk1), "+r" (blk2)
: "r" ((x86_reg)stride)
);
__asm__ volatile(
"movhlps %%xmm6, %%xmm0 \n\t"
"paddw %%xmm0, %%xmm6 \n\t"
"movd %%xmm6, %0 \n\t"
: "=r"(ret)
);
return ret;
}
What are the %1, %2, and %3? what does (%1,%2,%3) mean? Also what does "+r", "-r", "=r" mean?
You'll want to have a look at this GCC Inline Asssembly HOWTO.
The percent sign numbers are the instruction operands.
The inline assembler works similar to a macro preprocessor. Operands with exactly one leading percent are replaced by the the input parameters in the order as they appear in the parameter list, in this case:
%0 h output, register, r/w
%1 blk1 output, register, r/w
%2 blk2 output, register, r/w
%3 (x86_reg)stride input, register, read only
The parameters are normal C expressions. They can be further specified by "constraints", in this case "r" means the value should be in a register, opposed to "m" which is a memory operand. The constraint modifier "=r" makes this a write-only operand, "+r" is a read-write operand and "r" and normal read operand.
After the first colon the output operands appear, after the second the input operands and after the optional third the clobbered registers.
So the instruction sequence calculates the sum of the absolute differences in each byte of blk1 and blk2. This happens in 16 byte blocks, so if stride is 16, the blocks are contiguous, otherwise there are holes. Each instruction appears twice because some minimal loop unrolling is done, the h parameter is the number of 32 byte blocks to process. The second asm block seems to be useless, as the psadbw instruction sums up only in the low 16 bit of the destination register. (Did you omit some code?)

Resources