Reputation: 35
I am implementing a rotate function in AT&T 64 bit assembly and am having trouble getting the correct output in my code.
The function I'm trying to implement is
unsigned long rotate(unsigned long val, ul num, ul dir);
Val
is value I wanted rotated, num
is how many times and direction is left or right, 0 being right, 1 being left.
My assembly code:
.global rotate
rotate: #value = %rdi
#num = %rsi
#direction = %rdx
mov %rsi, %r10 #puts num into register
test %rdx, %rdx
jz right #if rdx is 0 jump to rotate right
#else go to loop right below which rotates left
loop:
test %r10, %r10 #if num is 0 I am done
jz done
rol $1, %rdi #rotate left 1 bit
dec %r10 #decrement my count
jmp loop #jump to top of loop
right: #same logic as left
test %r10, %10
jz done
rol $1, %rdi
dec %r10
jmp loop
done:
mov %rdi, %rax
ret
My C code:
#include <stdio.h>
extern unsigned long rotate(unsigned long val, unsigned long num, unsigned long direction);
int main()
{
unsigned long v,n,d;
v = 0xDEADBEEFDEADBEEF;
n = 2;
d = 1;
printf("%x\n ", rotate(v,n,d));
}
When I compile and run, I get the value 0x7AB6FBBF
, when I am supposed to get 0x7AB6FBBF7AB6FBBF
.
Is there something wrong with my instructions not sending in unsigned long
s or somethings?
Upvotes: 0
Views: 666
Reputation: 364180
You have a bug in your asm: the loop branch in right
does jmp loop
instead of jmp right
. At least that's one of your bugs, IDK if there are more. (update: @zch spotted the bug in your C which explains the truncation you're mentioning.)
This would have been easier to spot if you'd used a better name than loop
. e.g. left
.
But you shouldn't be looping anyway. x86 has rol %cl, %rdi
and ror %cl, %rdi
, which you can use instead of a loop. Simply mov
your shift count into %ecx
, like mov %esi, %ecx
.
Upvotes: 1
Reputation: 15278
printf("%x", a)
works on unsigned int
type. On unsigned long
you need to use "%lx"
as a format string.
Upvotes: 1