1
1
.text
2
2
3
3
/*
4
+ According to ABI documentation found at
5
+ http://www.x86-64.org/documentation.html
6
+ and Microsoft discussion at
7
+ http://msdn.microsoft.com/en-US/library/9z1stfyw%28v=VS.80%29.aspx.
8
+
9
+ BOTH CALLING CONVENTIONS
10
+
4
11
Callee save registers:
5
- ebp, ebx, esi, edi
12
+ R12--R15, RDI, RSI, RBX, RBP, RSP
13
+ XMM0--XMM5
6
14
7
15
Caller save registers:
8
- eax, ecx, edx
16
+ RAX, RCX, RDX, R8--R11
17
+ XMM6--XMM15
18
+ Floating point stack
19
+
20
+ MAC/AMD CALLING CONVENTIONS
21
+
22
+ Integer arguments go in registers:
23
+ rdi, rsi, rdx, rcx, r8, r9
24
+
25
+ User flags have no specified role and are not preserved
26
+ across calls, with the exception of DF in %rFLAGS,
27
+ which must be clear (set to "forward" direction)
28
+ on function entry and return.
29
+
30
+ MICROSOFT CALLING CONVENTIONS
31
+
32
+ Return value: RAX
33
+
34
+ First four arguments:
35
+ RCX, RDX, R8, R9
36
+ XMM0, XMM1, XMM2, XMM3
9
37
*/
10
38
11
39
/*
@@ -17,60 +45,55 @@ Caller save registers:
17
45
// swap_registers(registers_t *oregs, registers_t *regs)
18
46
.globl swap_registers
19
47
swap_registers:
20
- // save the old context
21
- movl 4 (%esp ), %eax
22
- //movl %eax, 0(%eax)
23
- movl %ebx , 4 (%eax )
24
- movl %ecx , 8 (%eax )
25
- movl %edx , 12 (%eax )
26
- movl %ebp , 16 (%eax )
27
- movl %esi , 20 (%eax )
28
- movl %edi , 24 (%eax )
29
- //movl %cs, 32(%eax)
30
- //movl %ds, 34(%eax)
31
- //movl %ss, 36(%eax)
32
- //movl %es, 38(%eax)
33
- //movl %fs, 40(%eax)
34
- //movl %gs, 42(%eax)
35
-
36
- // save the flags
37
- pushf
38
- popl %ecx
39
- movl %ecx , 44 (%eax )
48
+ // n.b. when we enter, the return address is at the top of
49
+ // the stack (i.e., 0(%RSP)). We
50
+ // simply save all NV registers into oregs.
51
+ // We then restore all NV registers from regs. This restores
52
+ // the old stack pointer, which should include the proper
53
+ // return address. We can therefore just return normally to
54
+ // jump back into the old code.
55
+
56
+ // Save instruction pointer:
57
+ popl %rax
58
+ movl %rax , 104 (%rdi )
40
59
41
- // save the return address as the instruction pointer
42
- // and save the stack pointer of the caller
43
- popl %ecx
44
- movl %esp , 28 (%eax )
45
- movl %ecx , 48 (%eax )
60
+ // Save non-volatile integer registers:
61
+ // (including RSP)
62
+ movl %rbx , 0 (%rdi )
63
+ movl %rsp , 8 (%rdi )
64
+ movl %rbp , 16 (%rdi )
65
+ movl %r12 , 24 (%rdi )
66
+ movl %r13 , 32 (%rdi )
67
+ movl %r14 , 40 (%rdi )
68
+ movl %r15 , 48 (%rdi )
46
69
47
- // restore the new context
48
- movl 4 (%esp ), %eax
70
+ // Save non-volatile XMM registers:
71
+ movl %xmm0 , 56 (%rdi )
72
+ movl %xmm1 , 64 (%rdi )
73
+ movl %xmm2 , 72 (%rdi )
74
+ movl %xmm3 , 80 (%rdi )
75
+ movl %xmm4 , 88 (%rdi )
76
+ movl %xmm5 , 96 (%rdi )
49
77
50
- movl 4 (%eax ), %ebx
51
- // save ecx for later...
52
- movl 12 (%eax ), %edx
53
- movl 16 (%eax ), %ebp
54
- movl 20 (%eax ), %esi
55
- movl 24 (%eax ), %edi
56
- movl 28 (%eax ), %esp
57
- // We can't actually change this...
58
- //movl 32(%eax), %cs
59
- //movl 34(%eax), %ds
60
- //movl 36(%eax), %ss
61
- //movl 38(%eax), %es
62
- //movl 40(%eax), %fs
63
- //movl 42(%eax), %gs
78
+ // Restore non-volatile integer registers:
79
+ // (including RSP)
80
+ movl 0 (%rsi ), %rbx
81
+ movl 8 (%rsi ), %rsp
82
+ movl 16 (%rsi ), %rbp
83
+ movl 24 (%rsi ), %r12
84
+ movl 32 (%rsi ), %r13
85
+ movl 40 (%rsi ), %r14
86
+ movl 48 (%rsi ), %r15
64
87
65
- // restore the flags
66
- movl 44 (%eax ), %ecx
67
- push %ecx
68
- popf
69
-
70
- // ok, now we can restore ecx
71
- movl 8 (%eax ), %ecx
72
-
73
- // Return!
74
- jmp *48 (%eax )
88
+ // Restore non-volatile XMM registers:
89
+ movl 56 (%rsi ), %xmm0
90
+ movl 64 (%rsi ), %xmm1
91
+ movl 72 (%rsi ), %xmm2
92
+ movl 80 (%rsi ), %xmm3
93
+ movl 88 (%rsi ), %xmm4
94
+ movl 96 (%rsi ), %xmm5
75
95
96
+ // Jump to the instruction pointer
97
+ // found in regs:
98
+ jmp *104 (%rsi )
76
99
0 commit comments