Reputation: 659
I tried translating this into C, but I'm stuck at the displacement of the memory address (%rdi
):
program:
movq (%rdi), %rax
testq %rax, %rax
je L1
addq $8, %rdi
movq %rax, %rdx
L3:
cmpq %rdx, %rax
cmovl %rdx, %rax
addq $8, %rdi
movq -8(%rdi), %rdx
testq %rdx, %rdx
jne L3
L1:
ret
I've come up with following so far:
int func(int *x){
int ret = *x;
if(ret != 0){
x+=8; //is this true?
y = ret;
while(y!=0){
if(ret<y){
ret = y;
}
y=?? //What should this say?
}
}
return ret;
Possible solution (waiting for someone to confirm):
int func(int *x){
int ret = *x;
if(ret!=0){
++x;
int y = ret;
while(y != 0){
if(ret < y){
ret = y;
}
++x;
y = x[-1];
}
}
return ret;
}
Upvotes: 0
Views: 904
Reputation: 16626
x+=8; //is this true?
No. x
is int *
, and on your current target platform int
is 64 bit wide, which is 8 bytes. In assembly you have raw pointer to bytes, as memory is addressable by bytes, so the add rdi,8
is in C like x = (int*)(((int8_t*)x)+8);
which can be shortened to ++x;
And if movq (%rdi), %rdx
is rdx = x[0]; // or " = *x;"
, then movq -8(%rdi), %rdx
is rdx = x[-1];
The remaining C part looks unfinished.
Warning, spoiler is following!
it will search through the
x
array until zero value is found (terminator), and keep updatingret
with smallest value found.
And it looks like my spoiler was wrong, the compare is probably the other way. Just to make sure, run both original asm in debugger, and your C, to see if they do the same thing. Also watching assembly in debugger single-stepping over instructions, checking how values in registers evolve, is often lot more descriptive and visual, than any long discussion. :) Sorry for not being sure, but the AT&T syntax is driving me nuts.
BTW, my "C" translation would look probably like this (let's say the asm is searching for "max" value in array, not "min" (I'm still only ~90% sure)):
int64_t func(int64_t *x) {
if (0 == *x) return 0;
int64_t ret = *x;
do {
if (ret < *x) ret = *x;
++x;
} while (0 != *x);
return ret;
}
Which gets translated by gcc v7.2 as (I had to change the int
to int64_t
to have 64b int
):
func(long*):
movq (%rdi), %rax
testq %rax, %rax
je .L1
movq %rax, %rdx
.L3:
cmpq %rdx, %rax
cmovl %rdx, %rax
addq $8, %rdi
movq (%rdi), %rdx
testq %rdx, %rdx
jne .L3
.L1:
rep ret
Which is almost identical to original assembly.
Upvotes: 2