Reputation: 86
I want to swap two int pointers.
I can do it in C like this
void swap(int* a, int* b)
int temp = *a;
*a = *b;
*b=temp;
Now I'm trying to do it in assembly but, and bear with me, I don't understand why this doesn't work
push %ebp
mov %esp,%ebp
mov 8(%ebp), %ecx #a
mov 12(%ebp), %ebx #b
mov (%ecx), %eax #move o a para temp
mov (%ebx), %ecx #move o b para o a
mov (%eax), %ebx #move o temp para o b
mov %ebp, %esp
pop %ebp
ret
Can someone explain what I'm doing wrong?
Upvotes: 1
Views: 4627
Reputation: 47573
Your C code is attempting to swap the values pointed to by pointers but your assembly code seems to be treating values as pointers leading to segmentation faults
. One way to handle this is to use extra register(s) to hold the pointers and the values they point to.
The 32-bit CDECL allows us to use EAX, ECX, and EDX without worrying about saving their values. We'll need a 4th register and we'll have to preserve it ourselves.
I will also assume you want the frame pointer present (the routine could be written without it):
push %ebp
mov %esp,%ebp
push %ebx # Preserve non-volatile EBX register
mov 8(%ebp),%eax # EAX = Pointer to a (arg1)
mov 12(%ebp),%edx # EDX = Pointer to b (arg2)
mov (%eax),%ecx # Temporarily save value at memory address a (*a) to ECX
mov (%edx),%ebx # Temporarily save value at memory address b (*b) to EBX
mov %ebx,(%eax) # Move value of b (EBX) to memory address of a (*a)
mov %ecx,(%edx) # Move value of a (ECX) to memory address of b (*b)
pop %ebx # Restore non-volatile EBX register
pop %ebp
ret
In theory you could remove the stack frame altogether (may make stack traces in the debugger harder to follow). The code could have used ESP to access the arguments rather than EBP:
push %ebx # Preserve non-volatile EBX register
mov 8(%esp),%eax # EAX = Pointer to a
mov 12(%esp),%edx # EDX = Pointer to b
mov (%eax),%ecx # Temporarily save value at memory address a (*a) to ECX
mov (%edx),%ebx # Temporarily save value at memory address b (*b) to EBX
mov %ebx,(%eax) # Move value of b (EBX) to memory address of a (*a)
mov %ecx,(%edx) # Move value of a (ECX) to memory address of b (*b)
pop %ebx # Restore non-volatile EBX register
ret
Note: Failing to preserve (per 32-bit CDECL calling convention) non-volatile registers like EBX, EBP, ESI, and EDI is a bug. In simple test code it may appear to work, but in more complex code with optimizations on you may experience undefined behaviour if the calling convention isn't strictly adhered to.
Upvotes: 1
Reputation: 61986
As Weather Vane said, the C code you have shown is not swapping two int pointers. It is swapping two ints pointed by two int pointers.
But in your assembly you appear to be trying to swap two ints pointed by two int pointers, so your code is not an entirely lost cause.
Study this to understand what it does, and then give it a try:
mov (%ecx), %eax
mov (%ebx), %edx
mov %edx, (%ecx)
mov %eax, (%ebx)
Upvotes: 1