3.25. SETJMP/LONGJMP
jmp_bufstructure usually comes undocumented, to preserve forward compatibility.
Let’s see how setjmp() implemented in MSVC 2013 x64:
...
; RCX = address of jmp_buf
mov [rcx], rax
mov [rcx+8], rbx
mov [rcx+18h], rbp
mov [rcx+20h], rsi
mov [rcx+28h], rdi
mov [rcx+30h], r12
mov [rcx+38h], r13
mov [rcx+40h], r14
mov [rcx+48h], r15
lea r8, [rsp+arg_0]
mov [rcx+10h], r8
mov r8, [rsp+0] ; get saved RA from stack
mov [rcx+50h], r8 ; save it
stmxcsr dword ptr [rcx+58h]
fnstcw word ptr [rcx+5Ch]
movdqa xmmword ptr [rcx+60h], xmm6
movdqa xmmword ptr [rcx+70h], xmm7
movdqa xmmword ptr [rcx+80h], xmm8
movdqa xmmword ptr [rcx+90h], xmm9
movdqa xmmword ptr [rcx+0A0h], xmm10
movdqa xmmword ptr [rcx+0B0h], xmm11
movdqa xmmword ptr [rcx+0C0h], xmm12
movdqa xmmword ptr [rcx+0D0h], xmm13
movdqa xmmword ptr [rcx+0E0h], xmm14
movdqa xmmword ptr [rcx+0F0h], xmm15
retn
It just populates jmp_buf structure with current values of almost all registers. Also, current value ofRAis
taken from the stack and saved in jmp_buf: it will be used as new value ofPCin future.
Now longjmp():
...
; RCX = address of jmp_buf
mov rax, rdx
mov rbx, [rcx+8]
mov rsi, [rcx+20h]
mov rdi, [rcx+28h]
mov r12, [rcx+30h]
mov r13, [rcx+38h]
mov r14, [rcx+40h]
mov r15, [rcx+48h]
ldmxcsr dword ptr [rcx+58h]
fnclex
fldcw word ptr [rcx+5Ch]
movdqa xmm6, xmmword ptr [rcx+60h]
movdqa xmm7, xmmword ptr [rcx+70h]
movdqa xmm8, xmmword ptr [rcx+80h]
movdqa xmm9, xmmword ptr [rcx+90h]
movdqa xmm10, xmmword ptr [rcx+0A0h]
movdqa xmm11, xmmword ptr [rcx+0B0h]
movdqa xmm12, xmmword ptr [rcx+0C0h]
movdqa xmm13, xmmword ptr [rcx+0D0h]
movdqa xmm14, xmmword ptr [rcx+0E0h]
movdqa xmm15, xmmword ptr [rcx+0F0h]
mov rdx, [rcx+50h] ; get PC (RIP)
mov rbp, [rcx+18h]
mov rsp, [rcx+10h]
jmp rdx ; jump to saved PC