aboutsummaryrefslogtreecommitdiff
path: root/exit_123.s
blob: 9fe9264a5d04e27748964681c724cbd74418df8f (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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

# || -> cont
.func main
	# push a new integer
	pushq $100
	pushq $INT_code
	mov %rsp, %r11 # backup first arg

	# push another new integer
	pushq $23
	pushq $INT_code
	mov %rsp, %r12 # backup second arg

	# push the plus
	push %r12
	push %r11
	pushq $2
	pushq $plus
	mov %rsp, %r13 # backup plus

	# push a cont thunk for main_exit
	push %rsi
	pushq $1
	pushq $main_exit

	# evaluate into main_exit
	mov %rsp, %rsi
	enter %r13

# exitcode -> | cont (unused, should be 0) |
.func main_exit
	mov 0x8(%rsi), %rdi # result to syscall exitcode
	mov $0x3c, %rax  # syscall 60
	syscall # exit %rdi

# | arg1 | arg2 | -> cont
.func plus
	# push a thunk for finishing the plus
	push %rsi # cont
	push %rbp # ret (self)
	mov 0x18(%rbp), %rax
	push %rax # arg2
	pushq $3
	pushq $plus_step1

	mov %rsp, %rsi # continue to the new thunk
	enter 0x10(%rbp) # evaluate arg1

# arg1 -> | arg2 | ret | cont |
.func plus_step1
	# this is guaranteed to be entered only once (it's a cont), so we can rewrite the thunk in place
	mov 0x10(%rbp), %rax
	movq $plus_fini, 0x00(%rbp)
	mov %rsi, 0x10(%rbp)

	mov %rbp, %rsi # continue on the rewritten thunk
	enter %rax # evaluate arg1

# arg2 -> | arg1 | ret | cont |
.func plus_fini
	mov 0x8(%rsi), %rax # arg 2 
	mov 0x10(%rbp), %rsi # location of arg1
	add 0x8(%rsi), %rax # arg 1

	mov 0x18(%rbp), %rsi # save result to the original plus thunk
	mov %rax, 0x08(%rsi)
	movq $INT_code, 0x00(%rsi)

	enter 0x20(%rbp) # eval cont, returning %rsi