2

例としてi386を考えてみてください。ただし、他のアーチにも同様の質問が当てはまります。jmp_bufによって保存される従来のi386は、 6つのsetjmp保存されたレジスタ、、、、、、、、およびで構成されます。これらのうち、最初の4つはABIごとに呼び出し元で保存されるため、呼び出された関数自体が、保存された独自の値で上書きします(からの最初の戻りと2番目の戻りの間で変更される場合があります)。したがって、これらのレジスタを?に保存することのポイントは何ですか?スタックと命令ポインタだけを保存するのも同様に機能しませんか?ebxesiediebpespeipsetjmpsetjmpjmp_buf

編集:私は誤って発信者保存と着信者保存を混同していました。これが混乱の原因でした。皆さんの時間を無駄にしてしまったことをお詫びします。

4

2 に答える 2

5

setjmp / longjmpペアは「goto」ではなく、「save-state / restore-state」コンボです...ほとんどのレジスタが保存されていない場合、これは不可能です。例外はサブルーチンの戻りレジスタであるため、setjmpの通常の呼び出しから戻ったか、longjmpを介して戻ったかを識別できます。

編集-あなたが質問した4つは呼び出し元が保存されているはずですが、setjmp()はあなたを信頼しません...そしてあなたが何をしたかに関係なく正しいことをします;)

于 2012-02-19T18:36:34.377 に答える
0

あなたはsetjumpそれらの値を上書きすると仮定していますが(公正な仮定)、longjmpターゲットが不安定になり、使用できなくなるため、そうなるとは思えません。

ebxに入るポインターがあったとしましょう。戻るsetjmpときに、そのポインターを復元する必要があります。そうしないと、適切な例外が発生する可能性があり、非ローカル goto のポイント全体が無効になります。longjmp

より実際に見てみると、MS CRT はレジスタを保存する前に汚染されていないことがわかります。

MSVCR100._setjmp3 7>MOV EDX,DWORD PTR SS:[ESP+4]
73A030C4            MOV DWORD PTR DS:[EDX],EBP
73A030C6            MOV DWORD PTR DS:[EDX+4],EBX
73A030C9            MOV DWORD PTR DS:[EDX+8],EDI
73A030CC            MOV DWORD PTR DS:[EDX+C],ESI
73A030CF            MOV DWORD PTR DS:[EDX+10],ESP
73A030D2            MOV EAX,DWORD PTR SS:[ESP]
73A030D5            MOV DWORD PTR DS:[EDX+14],EAX
73A030D8            MOV DWORD PTR DS:[EDX+20],56433230
73A030DF            MOV DWORD PTR DS:[EDX+24],0
73A030E6            MOV EAX,DWORD PTR FS:[0]
73A030EC            MOV DWORD PTR DS:[EDX+18],EAX
73A030EF            CMP EAX,-1
73A030F2            JNZ SHORT MSVCR100.73A030FD
73A030F4            MOV DWORD PTR DS:[EDX+1C],-1
73A030FB            JMP SHORT MSVCR100.73A03138
73A030FD            MOV ECX,DWORD PTR SS:[ESP+8]
73A03101            OR ECX,ECX                                                   ;  Switch (cases 0..8)
73A03103            JE SHORT MSVCR100.73A0310F
73A03105            MOV EAX,DWORD PTR SS:[ESP+C]
73A03109            MOV DWORD PTR DS:[EDX+24],EAX
73A0310C            DEC ECX
73A0310D            JNZ SHORT MSVCR100.73A03117
73A0310F            MOV EAX,DWORD PTR DS:[EAX+C]                                 ;  Cases 0,1 of switch 73A03101
73A03112            MOV DWORD PTR DS:[EDX+1C],EAX
73A03115            JMP SHORT MSVCR100.73A03138
73A03117            MOV EAX,DWORD PTR SS:[ESP+10]
73A0311B            MOV DWORD PTR DS:[EDX+1C],EAX
73A0311E            DEC ECX
73A0311F            JE SHORT MSVCR100.73A03138
73A03121            PUSH ESI
73A03122            PUSH EDI
73A03123            LEA ESI,DWORD PTR SS:[ESP+1C]
73A03127            LEA EDI,DWORD PTR DS:[EDX+28]
73A0312A            CMP ECX,6
73A0312D            JBE SHORT MSVCR100.73A03134
73A0312F            MOV ECX,6                                                    ;  Default case of switch 73A03101
73A03134            REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]               ;  Cases 3,4,5,6,7,8 of switch 73A03101
73A03136            POP EDI
73A03137            POP ESI
73A03138            SUB EAX,EAX                                                  ;  Case 2 of switch 73A03101
73A0313A            RETN

アップデート

環境を維持する必要があると述べている標準文書があります。

setjmp() の呼び出しは、後で longjmp() が使用するために、呼び出し環境をその env 引数に保存します。

于 2012-02-19T19:57:45.100 に答える