First of all, if you're trying to get your feet wet learning asm, GNU C inline asm is one of the hardest ways to use asm. Not only do you have to write correct asm, you have to spend a lot of time using esoteric syntax to inform the compiler of exactly what your code needs for input and output operands, or you will have a bad time. Writing whole functions in ASM is much easier. They can't be inlined, but it's a learning exercise anyway. The normal function ABI is much simpler than the boundary between C and inline ASM with constraints. See the x86 wiki...
Besides that compile error, you have a bug: you clobber %[a], even though you told gcc it's an input-only operand.
I assume this still a "work in progress", since you could get the same result with better code. (e.g. using %edx as a scratch reg is totally unnecessary.) Of course, in the general case where this is inlined into code where a might be a compile-time constant, or known to be related to something else, you'd get better code from just doing it in C (unless you spent a lot of time making inline-asm variants for various cases.)
int get_year(int a, int *b, char * c)
{
int ret, t1, t2;
asm (
"addl %[bval], %[a] \n\t"
"movb $58, 4 + %[cval]\n\t" // c is an "offsetable" memory operand
: [t1] "=&r" (t1), [cval] "=o" (*c)
: [a] "0" (a), [bval] "erm" (*b)
: // no longer clobbers memory, because we use an output memory operand.
);
ret = t1; // silly redundancy here, could have just used a as an input/output operand and returned it, since you apparently want the value
return ret;
}
This now compiles and assembles (using godbolt's "binary" option to actually assemble). The 4 + (%rdx) produces a warning, but does assemble to 4(%rdx). IDK how to write the offset in a way that doesn't error if there's already an offset. (e.g. if the operand is *(c+4), so the generated asm is 4 + 4(%rdx), it wouldn't work to leave out the +.)
This is still using the matching-output-operand trick, but I changed to using memory or general constraints to allow compiler-time constants to end up doing a addl $constant, %edi.
This allows the compiler as much flexibility as possible when inlining. e.g. if a caller ran get_year(10, &arr[10], &some_struct.char_member), it could use whatever addressing mode it wanted for the load and store, instead of having to generate c in a single register. So the inlined output could end up being movb $58, 4+16(%rbp, %rbx) for example, instead of forcing it to use 4(%reg).
t2to bechar*lldbdebugger?