summaryrefslogtreecommitdiff
path: root/src/libc/setjmp.asm
blob: a20a0af084d5adfbdc8110e00fb5772a54a1d251 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
[bits 32]

global setjmp
global longjmp

;typedef struct {
;	uint32_t ebx;
;	uint32_t esp;
;	uint32_t ebp;
;	uint32_t esi;
;	uint32_t edi;
;	uint32_t eip;
;} jmp_buf[1];

; int setjmp(jmp_buf env)
setjmp:
	mov eax, [esp+4]	; the adress of the jump buffer
	mov [eax], ebx		; safe registers
	mov [eax+4], esp
	mov [eax+8], ebp
	mov [eax+12], esi
	mov [eax+16], edi
	mov edx, [esp]		; get return address from the stack (pushed here by call)
	mov [eax+20], edx
	mov eax, 0		; indicate that we come from setjmp, not from a longjmp
	ret
	
; void longjmp(jmp_buf env, int value);
longjmp:
	mov eax, [esp+4]	; the address of the jump buffer
	mov ecx, [esp+8]	; the return value for setjmp
	mov ebx, [eax]		; restore registers
	mov esp, [eax+4]
	mov ebp, [eax+8]
	mov esi, [eax+12]
	mov edi, [eax+16]
	mov edx, [eax+20]	; get jump address and store it on the stack for 'ret'
	mov [esp], edx
	mov eax, ecx		; get return value
	cmp eax, 0
	jnz .return		; non zero, ok, return it
	mov eax, 1		; setjmp called with 0, not good, return 1
.return:
	ret