Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Xv6堆栈帧-eip的返回值是否损坏?_C_Assembly_Xv6 - Fatal编程技术网

C Xv6堆栈帧-eip的返回值是否损坏?

C Xv6堆栈帧-eip的返回值是否损坏?,c,assembly,xv6,C,Assembly,Xv6,我有以下代码试图在xv6中运行: void handle_signal(siginfo_t info) { printf(1, "Caught signal %d...\n", info.signum); if (info.signum == SIGFPE) printf(1, "TEST PASSED\n"); else printf(1, "TEST FAILED: wrong signal sent.\n"); return;

我有以下代码试图在xv6中运行:

void handle_signal(siginfo_t info)
{
    printf(1, "Caught signal %d...\n", info.signum);
    if (info.signum == SIGFPE)
        printf(1, "TEST PASSED\n");
    else
        printf(1, "TEST FAILED: wrong signal sent.\n");
    return;
}

int main(int argc, char *argv[])
{
   int x = 5;
   int y = 0;
   //int z = 0;
   signal(SIGFPE, handle_signal);

   x = x / y;
   //x = x / z;
   printf(1, "TEST FAILED: no signal sent.\n");

   return 0;
}
信号处理程序被推到堆栈上,如下所示:

void handle_signal(int signo, struct trapframe *tf){
     *((uint*)(tf->esp-4)) = tf->eip;
     *((uint*)(tf->esp-8)) = proc->tf->eax;
     *((uint*)(tf->esp-12)) = proc->tf->ecx;
     *((uint*)(tf->esp-16)) = proc->tf->edx;
     *((uint*)(tf->esp-20)) = signo;
     *((uint*)(tf->esp-24)) =(uint)proc->pop;
     tf->esp = tf->esp-24;
     tf->eip = (uint)(proc->sigHandlers[signo]);
}
因此,我将堆栈的底部设置为旧的指令指针,在本例中,它应该是指令

 x = x / y;
然后我推送易失性寄存器,推送信号处理程序参数,推送将弹出寄存器的函数,最后将eip(指令指针)设置为信号处理程序的地址

这是我的pop函数:

void popregs(void){
__asm__ (
"add $8, %esp;"
"pop %edx;"
"pop %ecx;"
"pop %eax;"
"ret");
}
通常,这段代码应该运行并陷入无限循环的SIGFPE调用中,因为每次处理程序运行时,我都会将指令指针设置回x=x/y调用。然而,由于某种原因,它会提前跳过并完成程序,然后用极不准确的EIP值分割错误

真正让我困惑的是,如果我在下面添加另一条指令,x=x/z,它就可以完美地工作。当我试图打印出程序的EIP时,它正确地指向x=x/y,所以它甚至没有执行x/z部分


有人能帮我理解吗?我正在努力理解堆栈中可能发生的事情

哈哈,每个人都有这个任务吗?:)无论如何,您对
popregs
中编译器生成的序言做出的假设可能是错误的。此外,你甚至不评论你从哪里得到的
添加$8,%esp
。更好的方法是将保存的寄存器放入
struct siginfo\u t
,并确保将其作为普通参数传递给popregs。我添加了8以从popregs函数的地址获取寄存器-这不对吗?可能对,也可能不对。这取决于编译器在asm语句之前发出的代码,可以是任何代码。你误用了内联汇编。你要么需要在汇编中编写整个函数,要么像Jester说的那样去做。哈哈,每个人都得到了这个任务吗?:)无论如何,您对
popregs
中编译器生成的序言做出的假设可能是错误的。此外,你甚至不评论你从哪里得到的
添加$8,%esp
。更好的方法是将保存的寄存器放入
struct siginfo\u t
,并确保将其作为普通参数传递给popregs。我添加了8以从popregs函数的地址获取寄存器-这不对吗?可能对,也可能不对。这取决于编译器在asm语句之前发出的代码,可以是任何代码。你误用了内联汇编。您要么需要在汇编中编写整个函数,要么执行Jester所说的操作。