0

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;
}
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
trev.
  • 13
  • 1
  • Can you explain what you are expecting each of these instructions to do? And which one is causing the fault? – Scott Hunter Apr 27 '21 at 19:03
  • You are assuming that `rcx` and `rbx` contain the required pointer values. Do they? – Weather Vane Apr 27 '21 at 19:05
  • 1
    How are you compiling your assembly? Please provide a minimal reproducible example. – h0r53 Apr 27 '21 at 19:07
  • 1
    Welcome to StackOverflow! Please take the [tour] and read "[ask]". Then come back and [edit] your question, providing a [example], please. – the busybee Apr 27 '21 at 19:08
  • 4
    The title says "swap contents of registers" yet the examples are about memory locations. To swap registers you can use `xchg`. – Weather Vane Apr 27 '21 at 19:09
  • 1
    Godbolt produces a different assembly (register usage, -O3 optimization): https://godbolt.org/z/dYYeYYrz1 – pmg Apr 27 '21 at 19:11
  • It is processor and system dependent. C does not not mandate *how* an implementation passes data to functions, or in which registers, or if any. – Weather Vane Apr 27 '21 at 19:14
  • Have you tried looking at compiler output for the working C function? That should show you which registers your pointer args arrive in, and which registers you can use as temporaries. – Peter Cordes Apr 28 '21 at 02:21

1 Answers1

3

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
Craig Estey
  • 30,627
  • 4
  • 24
  • 48
  • Huh, I'd been thinking the official title on https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf was x86-64, but actually you're right, the cover page calls it "System V Application Binary Interface AMD64 Architecture Processor Supplement" IDK why they moved away from x86-64 in v0.9 of the ABI (many years ago). (In case anyone's wondering, it's technically a "supplement" to the generic SysV ABI doc which covers some general ELF stuff I think. [Where is the x86-64 System V ABI documented?](https://stackoverflow.com/q/18133812)) – Peter Cordes Apr 28 '21 at 14:49