Just say:
asm("mov %1, %0\n\t" : "=m"(*(uint64_t*)(base + 8)) : "r"(data) : "memory");
The tricky thing is that when using the "m"
constraint, you're (possibly counterintuitively so) not giving an address but instead what in C looks like the "value" of the variable you want to change.
That's why, in this case, the weird pointer-cast-dereference. The compiler for this makes sure to put the address of the operand in.