从基于c中EBP的堆栈帧调用带有参数的函数

从基于c中EBP的堆栈帧调用带有参数的函数,c,gcc,assembly,x86,C,Gcc,Assembly,X86,我读了很多书,但有些问题还没有解决 我动态设计了一段代码 ; int xx_method_stub(void *fix_arg1, void* fix_arg2, void* arg3) push ebp ; 55 mov ebp, esp ; 89 E5 sub esp, imm8_local_size ; 83 EC imm8_local_size mov [ebp-4], imm_ptr_mid ; C7 45

我读了很多书,但有些问题还没有解决

我动态设计了一段代码

; int xx_method_stub(void *fix_arg1, void* fix_arg2, void* arg3)
push  ebp                   ; 55
mov   ebp, esp              ; 89 E5
sub   esp, imm8_local_size  ; 83 EC imm8_local_size
mov   [ebp-4], imm_ptr_mid  ; C7 45 FC imm_ptr_mid
jmp   rel16_offset          ; E9 rel16_offset
看看细节,可能有点太多了

现在它跳转到一个设计良好的地址,堆栈帧上下文如下所示:

16(%ebp)  - third function parameter
12(%ebp)  - second function parameter
 8(%ebp)  - first function parameter
 4(%ebp)  - old %EIP (the function's "return address")
 0(%ebp)  - old %EBP (previous function's base pointer)
-4(%ebp)  - first local variable
到目前为止,我需要
c
中的jmp标签代码

void stubthunk_init(stubthunk *stub, mid_t mid) {
    memcpy(stub, &stubthunk_templet, sizeof(stubthunk));
    stub->ph_mid = mid;
    stub->ph_eip_to_dispatch = (int) ((uintptr_t) dispatch - ((uintptr_t) stub + sizeof(stubthunk)));

// TODO retrieve stack variables as c-syntax local variables to make a function call in c for for portability.
//stack frame context
void *param_1; // 8(%%ebp)
void* param_2; //12(%%ebp)
void* local_1; //-4(%%ebp)

    disp:

#ifdef _MSC_VER
    __asm {
        mov param_1 [ebp+8]
        mov param_2 [ebp+12]
        mov local_1 [ebp-4]
    }
#else
    __asm__ __volatile(
        "mov 8(%%ebp), %0\n\t"
        "mov 12(%%ebp), %1\n\t"
        "mov -4(%%ebp), %2\n\t"
        :"=m" (param_1), "=m" (param_2), "=m" (local_1)
        :
        : /* clobbered register.  */
    );
#endif
    //USE #param_1 to restore or blance the stack
}
所以 是否有某种方法可以让在c中获取jmp代码块,并检索堆栈变量作为c语法局部变量,以便在
c
中进行函数调用,这样我就不必在
asm
中编写更多的代码,在这种情况下,无论函数调用约定如何,编译器都会帮助我,例如,arm,x86,x64

我希望我能自己在
c
中为函数和尾声设置堆栈框架。通过这种方式,我可以将函数改装成jmp代码块,并以自己的方式手动平衡堆栈

或者,像在masm中一样,有一个persudo指令
invoke
,例如
invoke MessageBox,NULL,addr MsgBoxText,addr MsgBoxCaption,MB_OK
,但它只存在于masm中

============更新=================

我的目标:

static native int foo(int otherArgsMaybeExist);
int stdcall Java_xx_foo(void *fixedArgEnv, void *fixedArgCls, jint otherArgsMaybeExist){
    return 0;
}

// TODO release stubthunk *stub
stubthunk *stub = (stubthunk*) alloc_code(sizeof(stubthunk));
stubthunk_init(stub, (intptr_t) argsize);
现在,我在内存中动态创建一个
stdcall
函数启动代码,它 除了一些必要的数据外,应该尽可能少(这里传递一个jmethodID,以便让后面的
解释\u stdcall\u x86
知道谁被调用)

在使用本机修饰符向
stub
注册java方法并输入本机世界后,它将进入我的代码。事实上,这就像在窗户上绕蹦床一样

跳转后,所有截获的方法将进入
解释\u stdcall\u x86
, 它负责堆栈平衡

它的原创性是这样的:

foo -> Java_xx_foo -> return
现在,将是这样的:

foo -> stubthunk + interpret_stdcall_x86 + blance the stack -> return
这里,
thubthunk
是硬代码,但使用指令动态创建。然而,我希望我可以使用
c
为exploration\u stdcall\u x86编写代码

=====================================


如果要在函数体中放置跳转目标,只需使用
asm volatile(“.globl my\u label\n”“my\u label:”)并从asm跳转到那里

不过,你不应该指望这会奏效

编译器对如何构建堆栈框架的选择取决于优化级别和内联,因此没有安全的方法来编写与您想要跳入的任何函数的结尾相匹配的asm


现在还不清楚这一切的目的是什么,以及为什么不能用C来实现。
您显示的内联asm已断开:

__asm__ __volatile(
    "mov 8(%%ebp), %0\n\t"   // mov mem,mem  isn't valid.
    "mov 12(%%ebp), %1\n\t"
    "mov -4(%%ebp), %2\n\t"
    :"=m" (param_1), "=m" (param_2), "=m" (local_1)
     // instead, use "=r" constraints to have the outputs in registers
     // from there, the compiler will put them where it wants them
    :
    : /* clobbered register.  */
);

我不认为自己从内联asm的堆栈中加载arg有什么意义。为什么不直接使用函数args,让编译器知道发生了什么???在32位或64位代码中,您唯一的选择是。当然,汇编程序会为您处理这些问题。使用操作数大小前缀来获取rel16编码也会用
0x0000FFFF
屏蔽EIP。那么您是想从asm跳到C函数的中间?现在还不清楚你通过使用asm获得了什么。为什么不能用C编写一个包装函数来操作参数并调用另一个函数呢?或者从asm,tail通过其正常入口点调用一个C函数(根据调用约定,arg位于它们通常的位置)“我不是100%清楚你在寻找什么,但似乎它们可能是相关的。有帮助的~我下一步会试试。的确,你是对的。我只是忍不住希望c局部变量可以附加寄存器或堆栈并分离。因为有多个文件,我创建了一个github测试,而ideone不能这样做。