Reputation: 1369
All is in the title, I have an int** as my function argument and I want to display the int with assembly, so what i've done is:
global bar
section .text:
bar:
mov rdx, [rdi]
mov rdi, [rdx]
mov rdx, [rdi]
mov rdi, [rdx]
call rsi
ret
My C code:
#include <stdio.h>
void bar(int **i, void (*f)()); //assembly function prototype
void foo(int i)
{
printf("%d\n", i);
}
int main(void)
{
int i = 3;
int *ptr = &i;
bar(&ptr, &foo);
return (0);
}
It segfaults and says "invalid address" at foo
with lldb, so I think it's because i'm not dereferencing the right way, so I'm stuck because I need to do this for a larger function. Thanks for the help.
Upvotes: 1
Views: 661
Reputation: 75062
Let me trace the assembly code:
global bar
section .text:
bar:
mov rdx, [rdi] // rdi = &ptr, rdx = *&ptr = ptr
mov rdi, [rdx] // rdx = ptr, rdi = *ptr = i
mov rdx, [rdi] // rdi = i, rdx = *i = (invalid)
mov rdi, [rdx]
call rsi
ret
This suggests actually you have to pass int****
, not int**
, as the first argument because you are doing dereference 4 times.
It will be like this:
#include <stdio.h>
void bar(int ****i, void (*f)()); //assembly function prototype
void foo(int i)
{
printf("%d\n", i);
}
int main(void)
{
int i = 3;
int *ptr = &i;
int **pptr = &ptr;
int ***ppptr = &pptr;
bar(&ppptr, &foo);
return (0);
}
Also stack pointer should be 16-byte aligned on function call in x86-64, so the assembly function bar
should be (for example):
global bar
section .text:
bar:
mov rdx, [rdi]
mov rdi, [rdx]
mov rdx, [rdi]
mov rdi, [rdx]
sub rsp, 8 // adjust stack pointer
call rsi
add rsp, 8 // restore stack pointer
ret
The alignment is done before call
and 8 byte (return address) is pushed by call
, so another 8 byte should be subtracted from the function pointer to retain 16-byte alignment.
If you want to use int**
as the first argument, do dereferences (memory accesses) only 2 times.
global bar
section .text:
bar:
mov rdx, [rdi]
mov rdi, [rdx]
sub rsp, 8
call rsi
add rsp, 8
ret
Another thing you may want to do is
global bar
section .text:
bar:
push rbp // create stack frame
mov rbp, rsp
sub rsp, 16 // create region for local variables (note 16-byte alignment)
mov [rbp-8], rdi // save the argument to the memory
mov rdx, [rdi]
mov rdi, [rdx]
mov rdi, [rbp-8] // restore the argument from the memory
mov rdx, [rdi]
mov rdi, [rdx]
call rsi
leave // destruct stack frame
ret
Upvotes: 4
Reputation: 50831
I think you might want this:
bar:
mov rax, [rdi]
mov edi, [rax]
call rsi
ret
which would match the void bar(int **i, void (*f)())
prototype
Upvotes: 2