2

此代码适用于我的本科操作系统课程。我试图在 new_sp 的同一堆栈上调用一个函数,然后返回到 new_sp 正在做的任何事情。它不起作用,我什至不确定如何调试它。建议或解决方案会很棒。我试图通过如果有什么我遗漏了请告诉我。

注意:它是我们在课堂上使用的特殊操作系统(xinu)的一部分。该函数是从 c 代码中调用的。我使用的参考:http ://www.unixwiz.net/techtips/win32-callconv-asm.html

这部分代码是在进程退出之前将进程保存到堆栈中的部分。new_sp 指向的堆栈也以这种方式保存。

    .text
    .globl  callsw

    /*---------------------------------------------------------------------
    * callsw -  call is callsw(&old_sp, &new_sp, &call_back)
    *---------------------------------------------------------------------*/
callsw:
    /*keep all of the old contex switch instructions so it will work with
      with cxtsw*/
    pushl   %ebp          /* push ebp onto stack          */
    movl    %esp,%ebp       /* record current SP in ebp     */
    pushfl                  /* record flags                 */
    pushal                  /* save general regs on stack   */

    /* save old segment registers here, if multiple allowed */

    movl    8(%ebp),%eax    /* Get mem location in which to */
    /*  save the old process's SP   */
    movl    %esp,(%eax)     /* save old process's SP        */
    movl    12(%ebp),%eax   /* Get location from which to   */

这里开始切换到回调函数的代码。我希望回调函数运行,然后返回执行与 new_sp 堆栈相关的代码。

    /* Switch to a new stach instead */

    movl    (%eax),%esp     /* pick up new process's SP     */

    /* restore new seg. registers here, if multiple allowed */

    popal                   /* restore general registers    */
    movl    (%ebp),%eax     /*keep old ebp for acess to arg 3*/
    movl    4(%esp),%ebp    /* pick up ebp before restoring */
    /*   interrupts                 */
    popfl                   /* restore interrupt mask       */
    add     $4,%esp         /* skip saved value of ebp      */
/* Switch to a new call back instead */

    movl    (%eax),%esp     /* pick up new process's SP     */

    /* restore new seg. registers here, if multiple allowed */

    popal                   /* restore general registers    */
    movl    (%ebp),%eax     /*keep old ebp for acess to arg 3*/
    movl    4(%esp),%ebp    /* pick up ebp before restoring */
    /*   interrupts                 */
    popfl                   /* restore interrupt mask       */
    add     $4,%esp         /* skip saved value of ebp      */

这是我尝试设置堆栈并跳转到新进程的地方。我调用的函数是没有参数也没有返回值的 ac 函数。

    pop     %ebx /* save the ra*/

    movl    %esp,%ebp /* move the base pointer to the bottom of the stack */
    add     -18,%ebp /* move stack down*/
    /*set up stack and jump */
    movl    %ebp,%esp /* nothing on stack they are = */
    movl    %ebx, 0(%ebp) /* save ebp to stack */
    movl    %ebx, 4(%ebp) /* save ra */
    movl    16(%eax),%ecx
    JMP (%ecx)     /* jump to call_back        */
4

1 回答 1

3

我认为你的问题在这里:

popal                   /* restore general registers    */
movl    (%ebp),%eax     /*keep old ebp for acess to arg 3*/

popal从保存在您要切换到的堆栈中的寄存器中恢复所有寄存器(包括 ebp)。所以movl (%ebp),%eax从新堆栈中加载一个值(实际上是%ebp属于调用者的值callsw。所以当你以后做

movl    (%eax),%esp     /* pick up new process's SP     */

你没有得到新进程的 SP——你从堆栈的上两层(callsw 的调用者的调用者)获取帧指针。

于 2013-04-09T04:44:19.823 回答