如何获取函数上的指针';C语言中的s参数?
在C语言中是否有一个通用的方法来获取每个参数的指针 你会使用vararg函数吗 特殊语法,如$1、$2、$3 如果没有,是否有一些预处理器宏来定义它 如果在C中不可能,我也对一个客观的C解决方案感兴趣。 我知道我可以在当前方法上使用_cmdspecial hidden获取选择器 参数是否有某种_arg1,_arg2?? 也可以在_cmd之后直接指向内存吗?它是 “安全”考虑参数指针彼此相邻? 更新我自己的问题 如果我使用一些汇编代码访问帧堆栈,我可以获得一个保持 在ebp正确的函数指针上?那么可以访问参数吗如何获取函数上的指针';C语言中的s参数?,c,dynamic,macros,arguments,c-preprocessor,C,Dynamic,Macros,Arguments,C Preprocessor,在C语言中是否有一个通用的方法来获取每个参数的指针 你会使用vararg函数吗 特殊语法,如$1、$2、$3 如果没有,是否有一些预处理器宏来定义它 如果在C中不可能,我也对一个客观的C解决方案感兴趣。 我知道我可以在当前方法上使用_cmdspecial hidden获取选择器 参数是否有某种_arg1,_arg2?? 也可以在_cmd之后直接指向内存吗?它是 “安全”考虑参数指针彼此相邻? 更新我自己的问题 如果我使用一些汇编代码访问帧堆栈,我可以获得一个保持 在ebp正确的函数指针上?那么可
同样的方式?很抱歉,如果这是显而易见的,我对汇编程序了解不多。不,唯一可以做到这一点的方法是使用
stdarg.h中提供的宏。不,唯一可以做到这一点的方法是使用stdarg.h中提供的宏。请参见和a。参见和a。不,没有特殊的方法,或任何特殊符号
我想您可以定义一个宏来获取每个参数并生成指向它的指针(找到Boost预处理器库);我肯定我不想
int somefunc(int arg1, char *arg2)
{
int *p_arg1 = &arg1;
char **p_arg2 = &arg2;
...
}
不,没有特殊的方法,也没有任何特殊的符号
我想您可以定义一个宏来获取每个参数并生成指向它的指针(找到Boost预处理器库);我肯定我不想
int somefunc(int arg1, char *arg2)
{
int *p_arg1 = &arg1;
char **p_arg2 = &arg2;
...
}
如果变量函数的所有参数都具有相同的类型(例如,void*
),则可以执行以下操作:
type nth_arg(va_list ap, size_t n)
{
va_list ap2;
va_copy(ap2, ap);
while (n--) va_arg(ap2, type);
return va_arg(ap2, type);
}
将type
替换为实际类型。如果变量函数的所有参数都具有相同的类型(例如void*
),可以执行以下操作:
type nth_arg(va_list ap, size_t n)
{
va_list ap2;
va_copy(ap2, ap);
while (n--) va_arg(ap2, type);
return va_arg(ap2, type);
}
将类型
替换为实际类型。在您的情况下,可以提取当前和以前的堆栈帧指针(即bp寄存器),并使用标准堆栈帧结构确定有多少个4字节(对于32位应用程序)参数单位已在当前例程的调用中传递。您将无法确定哪些单位是char、short或long,以及其中两个单位是否可能是long-long/\uu-int64参数
我想了很久了。考虑一个典型的函数调用“FUNC(A,B)”。调用代码,除非寄存器中有参数(某些x86-32编译器选项和英特尔建议的x86-64),否则代码结果如下
; long *esp,*ebp;
push b ; *(--esp)=b;
push a ; *(--esp)=a;
call func ; *(--esp)=return_address_location;
return_address_location:
add esp,8 ; esp+=2; // free memory allocated for passing parameters
然后,您将使用func进行处理
func:
push ebp ; *(--esp)=(long) ebp; // save current ebp <=> current stack frame
mov ebp,esp ; ebp=esp; // create new stack frame in ebp
sub esp,16 ; esp-=4; // reserve space for local variables <=> sizeof(long)*4
(func code ...)
func:
推动ebp*(-esp)=(长)ebp;//保存当前ebp当前堆栈帧
mov-ebp,esp;ebp=esp;//在ebp中创建新堆栈帧
副esp,16岁;esp-=4;//为局部变量sizeof(长)*4保留空间
(职能代码…)
现在,当您在func中,需要访问参数时,可以使用ebp+2和ebp+3(*ebp包含以前的ebp,ebp+1返回地址)对其进行寻址。当您需要访问局部变量时,可以使用ebp-4到ebp-1对其进行寻址(如果它们不都是长的,并且设置了一些打包选项,则可能会过于简化)
一段时间后,func完成了它的工作,您需要返回:
mov esp,ebp ; esp=ebp; // unreserve space for local variables
pop ebp ; ebp=*(esp++); // restore previous ebp <=> previous stack frame
ret ; eip=*(esp++); // pop return address into instruction pointer
mov-esp,ebp;esp=ebp;//为局部变量取消保留空间
弹出ebp;ebp=*(esp++);//恢复上一个ebp上一个堆栈帧
ret;eip=*(esp++);//将返回地址弹出到指令指针中
从第一个代码段中,您还将看到第一个堆栈分配(用于传递参数)在返回后是如何被释放的
以下是一些提示:
- 你自己做数学题
单步执行(通过
指令)通过呼叫/返回
序列,你会得到如何的想法
来解决原来的问题。这个
是基本的堆栈处理,看起来
对所有人来说都差不多
体系结构和实现
知道这件事是件好事
- 想象一个计算错误的
memset/memcpy到本地缓冲区和
它将如何销毁服务器上的数据
堆栈,包括返回地址,
以前的堆栈帧等
- 注意ds和ss中的值
(数据和堆栈选择器)和如果
它们包含完全相同的值a
您的解决方案可以使用memcpy
将参数从堆栈复制到
用于检查或存储的数据存储器
如果有帮助的话
- 如果ds=ss,您可以使用&来查找
从中传递的参数的地址
内部函数(¶m1和¶m2)
- 如果ds和ss不相等(如
可能是多线程的
应用程序)您将需要一个
使用“far”的memcpy变体
寻址“哪个将处理
ds和ss不同的情况
在您的情况下,提取当前和以前的堆栈帧指针(即bp寄存器)是可能的,但可能不是完全有用的,并使用标准堆栈帧结构确定有多少个4字节(对于32位应用程序)在调用当前例程时已传递参数单位。您将无法确定哪些单位是字符、短单位或长单位,以及它们中的两个单位是否可能是长/长参数
我想了更多。考虑一个典型的函数调用“FUNC(A,B)”。调用代码除非在寄存器中有参数(一些X8632编译器选项和英特尔建议的X8664),否则代码会变成这样的
。
; long *esp,*ebp;
push b ; *(--esp)=b;
push a ; *(--esp)=a;
call func ; *(--esp)=return_address_location;
return_address_location:
add esp,8 ; esp+=2; // free memory allocated for passing parameters
然后,您将使用func进行处理
func:
push ebp ; *(--esp)=(long) ebp; // save current ebp <=> current stack frame
mov ebp,esp ; ebp=esp; // create new stack frame in ebp
sub esp,16 ; esp-=4; // reserve space for local variables <=> sizeof(long)*4
(func code ...)
func:
按ebp;*(-esp)=(长)ebp;//保存当前ebp当前堆栈帧
mov ebp,esp;ebp=esp;//在ebp中创建新堆栈帧
子esp,16;esp-=4;//为局部变量sizeof(长)*4保留空间
(职能代码…)
现在,当您在func中,需要访问参数时,可以使用ebp+2和ebp+3(*ebp包含以前的ebp,ebp+1返回