在汇编代码中,更改堆栈指针+跳转 - >段错误?

时间:2018-05-02 16:08:10

标签: gcc x86 inline-assembly att

这是第一次在此处上传问题。 我必须做一个函数:

  1. 参数是:目标函数&全局数组
  2. 设置寄存器%ebp& %esp = array
  3. 设置寄存器%eip =目标函数
  4. 使用 asm ,C
  5. 中的内联汇编代码

    如果我忽略了第二个条件,那就不难了:

    void jump(unsigned int function);
    void goal();
    
    void main(){
        jump((unsigned int)goal); // call jump(goal)
    }
    
    void jump(unsigned int function){
        __asm__ __volatile__(
                "movl %0, %%eax;"
                "jmp %%eax" // jump to 'entry'
                ::"m"());
    }
    
    void goal(){ // desired destination of %eip
        printf("goal\n"); // if jmp instruction was successful, put 'goal'
        for(;;) { sleep(1); }
    }
    

    它确实提出了目标'。

    但是,每当我尝试更改%esp& %ebp以类似的方式失败:

    (主要变化只是在 asm 中间声明'数组'和2行

    int array[100]; // target array
    void jump(unsigned int function, unsigned int array);
    void goal();
    
    void main(){
        jump((unsigned int)goal, (unsigned int)array); // call jump(goal,array)
    }
    
    void jump(unsigned int function, unsigned int array){
        __asm__ __volatile__(
                "movl %0, %%eax;"
                "movl %1, %%ebx;"
    
                "movl %%ebx, %%esp;" // %esp = array
                "movl %%ebx, %%ebp;" // %ebp = array
    
                "jmp %%eax"
                ::"m"(function),"m"(array));
    }
    
    void goal(){
        printf("goal\n");
        for(;;) { sleep(1); }
    }
    

    这会导致分段错误。

    在'目标'的.s文件条目中函数包含所有函数的序言,即

    pushl %ebp
    movl %esp, %ebp
    

    所以我的第一个猜测是,通过%ebp或%esp指向全局数组,然后执行push,pop或mov会导致段错误。

    为验证这一点,我修改了装配零件如下:

             __asm__ __volatile__(
             "movl %0, %%eax;"
             "movl %1, %%ebx;"
             "movl %%ebp, %%ecx;" // %ecx : backup of %ebp
    
             "movl %%ebx, %%esp;"
             "movl %%ebx, %%ebp;" // %esp & %ebp = 'array'
    
             "pushl %%ebp;"
             "movl %%esp, %%ebp;" // instructions as in the entry of 'goal'
    
             "movl %%ecx, %%esp;"
             "movl %%ecx, %%ebp;" // restore %esp & %ebp before jmp
    
             "jmp %%eax"
             ::"m"(function),"m"(array));
    

    所以%esp和%ebp指向'数组'并按照“目标”中的说明进行操作。在jmp之前。

    令人惊讶的是,没有发生分段错误,但是出现了“目标”。根据需要。

    总之,

    1. 更改%esp& %ebp并不重要。
    2. jmp也有效。
    3. 但两者都会造成分段错误。
    4. 我用Google搜索,特别是在这里看看有人遇到这种现象并找到答案。不幸的是一无所获。

      希望得到帮助。

0 个答案:

没有答案