Почему setjmp традиционно сохраняет регистры? - PullRequest
1 голос
/ 19 февраля 2012

Просто рассмотрим i386 в качестве примера, но аналогичный вопрос относится и к другим аркам. Традиционный i386 jmp_buf, сохраняемый setjmp, состоит из 6 сохраненных регистров: ebx, esi, edi, ebp, esp и eip. Из них первые 4 сохраняются вызывающим абонентом в соответствии с ABI, поэтому функция, вызвавшая setjmp, сама перезапишет их своими собственными сохраненными значениями (которые могут изменяться между первым и вторым возвращением с setjmp). Таким образом, какой смысл вообще сохранять эти регистры в jmp_buf? Разве это не сработало бы так же, чтобы сохранить только указатели стека и инструкций?

Редактировать: Я ошибочно смешивал сохраненные вызывающим и сохраняемым номерами, что и стало источником всей путаницы. Извиняюсь за трату времени всех.

Ответы [ 2 ]

4 голосов
/ 19 февраля 2012

Пара setjmp / longjmp - это не "goto", это комбо "save-state / restore-state" ... это было бы невозможно, если бы большинство регистров не были сохранены; Исключением является регистр возврата подпрограммы, поэтому вы можете определить, вернулись ли вы после обычного вызова setjmp или с помощью longjmp.

Изменить - хотя четыре вопроса, которые вы спрашиваете, должны быть сохранены вызывающим, setjmp () не будет доверять вам ... и будет делать правильные вещи независимо от того, что вы сделали;)

0 голосов
/ 19 февраля 2012

Вы предполагаете, что setjump перезапишет эти значения (справедливое предположение), однако я сомневаюсь, что это могло бы произойти, потому что это привело бы к тому, что longjmp цели стали нестабильными, что делало бы невозможным использование.

допустим, у ebx есть указатель, входящий в setjmp, когда 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 () должен сохранить вызывающую среду в аргументе env дляпозже использовать longjmp ().

...