I'm trying to do a real simple assembler program to swap the contents of registers. This is what i've tried:
movq (%rcx), %rax
movq (%rbx), %rdx
movq %rdx, (%rcx)
movq %rax, (%rbx)
ret
It gives me segmentation fault.
Here is an example of a working program in c:
void swap(int64_t *a, int64_t *b) {
int64_t c = *a;
*a = *b;
*b = c;
}
See: https://en.wikipedia.org/wiki/X86_calling_conventions
You neglected to mention whether you're compiling for Microsoft/Win x64 or for the System V AMD64 ABI [or for something else entirely].
You are using AT&T asm syntax, so I'm assuming you want the SysV calling convention. (Since tools like GCC and GAS are more common on Linux / MacOS. But if you're using MinGW w64 on Windows then you'll want the Windows convention.)
You're assuming the args are in: %rcx
and %rbx
. This does not correspond with either convention [although it is somewhat closer to the MS ABI]
For System V AMD64 ABI (e.g. Linux, BSD, MacOS), the first two args are passed in %rdi
and %rsi
respectively. And, not in %rdx
and %rcx
(which are for the 3rd and 4th args).
You can always use %rax
and %rdx
as temp regs because %rax
holds the function return value and %rdx
is an arg reg so caller won't expect them to be preserved.
So, you want:
# Non-Windows
movq (%rdi),%rax
movq (%rsi),%rdx
movq %rdx,(%rdi)
movq %rax,(%rsi)
ret
For MS 64 bit, the arg registers are: %rcx, %rdx, %r8, %r9
So, you'd want:
# Windows
movq (%rcx),%rax
movq (%rdx),%r8
movq %r8,(%rcx)
movq %rax,(%rdx)
ret