如何在 ASMx64 中多次取消引用指针?
How to dereference a pointer multiple times in ASMx64?
一切都在标题中,我有一个 int** 作为我的函数参数,我想用汇编显示 int,所以我所做的是:
global bar
section .text:
bar:
mov rdx, [rdi]
mov rdi, [rdx]
mov rdx, [rdi]
mov rdi, [rdx]
call rsi
ret
我的C代码:
#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);
}
使用 lldb 在 foo
处出现段错误并显示“无效地址”,所以我认为这是因为我没有以正确的方式取消引用,所以我被卡住了,因为我需要为更大的对象执行此操作功能。感谢您的帮助。
让我跟踪汇编代码:
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
这表明实际上您必须传递 int****
,而不是 int**
作为第一个参数,因为您正在执行 4 次取消引用。
会变成这样:
#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);
}
此外,在 x86-64 中调用函数时堆栈指针应为 16 字节对齐,因此汇编函数 bar
应为(例如):
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
对齐在call
之前完成,8字节(return地址)被call
压入,所以函数指针要减去另外8字节保留16-字节对齐。
如果你想使用 int**
作为第一个参数,只进行 2 次解引用(内存访问)。
global bar
section .text:
bar:
mov rdx, [rdi]
mov rdi, [rdx]
sub rsp, 8
call rsi
add rsp, 8
ret
您可能想做的另一件事是
- 创建栈帧
- 将参数存储在堆栈内存中以备后用
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
我想你可能想要这个:
bar:
mov rax, [rdi]
mov edi, [rax]
call rsi
ret
这将匹配 void bar(int **i, void (*f)())
原型
一切都在标题中,我有一个 int** 作为我的函数参数,我想用汇编显示 int,所以我所做的是:
global bar
section .text:
bar:
mov rdx, [rdi]
mov rdi, [rdx]
mov rdx, [rdi]
mov rdi, [rdx]
call rsi
ret
我的C代码:
#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);
}
使用 lldb 在 foo
处出现段错误并显示“无效地址”,所以我认为这是因为我没有以正确的方式取消引用,所以我被卡住了,因为我需要为更大的对象执行此操作功能。感谢您的帮助。
让我跟踪汇编代码:
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
这表明实际上您必须传递 int****
,而不是 int**
作为第一个参数,因为您正在执行 4 次取消引用。
会变成这样:
#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);
}
此外,在 x86-64 中调用函数时堆栈指针应为 16 字节对齐,因此汇编函数 bar
应为(例如):
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
对齐在call
之前完成,8字节(return地址)被call
压入,所以函数指针要减去另外8字节保留16-字节对齐。
如果你想使用 int**
作为第一个参数,只进行 2 次解引用(内存访问)。
global bar
section .text:
bar:
mov rdx, [rdi]
mov rdi, [rdx]
sub rsp, 8
call rsi
add rsp, 8
ret
您可能想做的另一件事是
- 创建栈帧
- 将参数存储在堆栈内存中以备后用
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
我想你可能想要这个:
bar:
mov rax, [rdi]
mov edi, [rax]
call rsi
ret
这将匹配 void bar(int **i, void (*f)())
原型