2

このコードは、私の学部 OS コース用です。new_sp の同じスタックで関数を呼び出してから、new_sp が行っていたことに戻ろうとしています。機能しておらず、バグを修正する方法もわかりません。提案または解決策は素晴らしいでしょう。やり残したことがある場合は、私に知らせてください。

注: これは、クラスで使用している特別な OS (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 を取得していません。スタックの 2 レベル上 (callsw の呼び出し元の呼び出し元) からフレーム ポインターを取得しています。

于 2013-04-09T04:44:19.823 に答える