forked from lmartinho/pgubook-macos-x86-64
-
Notifications
You must be signed in to change notification settings - Fork 0
/
alloc.asm
283 lines (239 loc) · 10.1 KB
/
alloc.asm
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
%include "xnu.asm"
extern _sbrk
; PURPOSE: Program to manage memory usage - allocates
; and deallocates memory as requested
;
; NOTES: The programs using these routines will ask
; for a certain size of memory. We actually
; use more than that size, but we put it
; at the beginning, before the pointer
; we hand back. We add a size field and
; an AVAILABLE/UNAVAILABLE marker. So, the
; memory looks like this
;
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;; Available Marker ;; Size of memory ;; Actual memory locations ;;
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ^--Returned pointer
; points here
; The pointer we return only points to the actual
; locations requested to make it easier for the
; calling program. It also allows us to change our
; structure without the calling program having to
; change at all.
section .data
; GLOBAL VARIABLES
; This points to the beginning of the memory we are managing
heap_begin:
dq 0
; This points to one location past the memory we are managing
current_break:
dq 0
; STRUCTURE INFORMATION
; Size of space for memory region header
HEADER_SIZE equ 8
; Location of the "available" flag in the header
HDR_AVAIL_OFFSET equ 0
; Location of the size field in the header
HDR_SIZE_OFFSET equ 4
; CONSTANTS
UNAVAILABLE equ 0 ; This is the number we will use to mark
; space that has been given out
AVAILABLE equ 1 ; This is the number we will use to mark
; space that has been returned, and is
; available for giving
SYS_BRK equ 0x2000017 ; (currently unused) System call number for
; the break function
SYS_SBRK equ 0x2000069 ; (currently unused)
section .text
; FUNCTIONS
;; allocate_init ;;
; PURPOSE: Call this function to initialize the
; functions (specifically, this sets the heap_begin and
; current_break). This has no parameters and no
; return value.
global allocate_init
allocate_init:
push rbp ; function prologue
mov rbp, rsp
sub rsp, 16 ; performs required stack alignment before system call
; If the brk system call is called with 0, it
; returns the last valid usable address
; We're using the C std lib sbrk with 0 increment to determine the last valid usable address
xor edi, edi ; pass 0 to sbrk to retrieve the current break
call _sbrk
inc rax ; rax now has the last valid
; address, and we want the
; memory location after that
mov [rel current_break], rax ; store the current break
mov [rel heap_begin], rax ; store the current break as our
; first address. this will cause
; the allocate function to get
; more memory from Linux the
; first time it is run
add rsp, 16 ; function epilogue
mov rsp, rbp
pop rbp
ret
;; allocate ;;
; PURPOSE: This function is used to grab a section of
; memory. It checks to see if there are any
; free blocks, and, if not, it asks MacOS
; for a new one.
;
; PARAMETERS: This function has one parameter - the size
; of the memory block we want to allocate
;
; RETURN VALUE:
; This function returns the address of the
; allocate memory in rax. If there is no
; memory available, it will return 0 in rax.
;
; PROCESSING:
; Variables used:
;
; rcx - hold the size of the requested memory
; (first/only parameter)
; rax - current memory region being examined
; rbx - current break position
; rdx - size of the current memory region
;
; We scan through each memory region starting with
; heap_begin. We look at the size of each one, and if
; it has been allocated. If it's big enough for the
; requested size, and its available, it grabs that one.
; If it does not find a region large enough, it asks
; MacOS for more memory. In that case, it moves
; current_break up.
global allocate
ST_MEM_SIZE equ 16 ; stack position of the memory size
; to allocate
allocate:
push rbp ; standard function stuff
mov rbp, rsp
mov rcx, [rbp + ST_MEM_SIZE] ; rcx will hold the size
; we are looking for (which is the first
; and only parameter)
mov rax, [rel heap_begin] ; rax will hold the current
; search location
mov rbx, [rel current_break] ; rbx will hold the current
; break
alloc_loop_begin: ; here we iterate through each
; memory region
cmp rax, rbx ; need more memory if these are equal
je move_break
; grab the size of this memory
mov edx, [rax + HDR_SIZE_OFFSET]
; if the space is unavailable,
; go to the next one
cmp dword [rax + HDR_AVAIL_OFFSET], UNAVAILABLE
je next_location
cmp rdx, rcx ; If the space is available, compare
jle allocate_here ; the size to the needed size. If its
; big enough, go to allocate_here
next_location:
add rax, HEADER_SIZE ; The total size of the memory
add rax, rdx ; region is the sum of the size
; requested (currently stored
; in rdx), plus another 8 bytes
; for the header (4 for the
; AVAILABLE/UNAVAILABLE flag,
; and 4 for the size of the
; region). So, adding rdx and 8
; to rax will get the address
; of the next memory region
jmp alloc_loop_begin ; go look for the next location
allocate_here: ; if we've made it here,
; that means that the
; region header of the region
; to allocate is in rax
; mark space as unavailable
mov dword [rax + HDR_AVAIL_OFFSET], UNAVAILABLE
add rax, HEADER_SIZE ; move rax past the header to
; the usable memory (since
; that's what we return)
mov rsp, rbp
pop rbp
ret
move_break: ; if we've made it here, that
; means that we've exhausted
; all addressable memory, and
; we need to ask for more.
; rbx holds the current
; endpoint of the data,
; and rcx holds its size
push rcx
push rbx
; We need to adapt to MacOS
mov rdi, rcx ; rdi will hold the increment
add rdi, HEADER_SIZE ; add space for the headers
call _sbrk ; now its time to ask MacOS
; for more memory
; under normal conditions, this should
; return the new break in %rax, which
; will be either 0 if it fails, or
; it will be equal to or larger than
; we asked for. We don’t care
; in this program where it actually
; sets the break, so as long as %eax
; isn’t 0, we don’t care what it is
cmp rax, 0 ; check for error conditions
je error
pop rbx ; restore saved registers
pop rcx
; set this memory as unavailable, since we're about to
; give it away
mov dword [rax + HDR_AVAIL_OFFSET], UNAVAILABLE
; set the size of the memory
mov dword [rax + HDR_SIZE_OFFSET], edx
; move rax to the actual start of usable memory.
; rax now holds the return value
add rax, HEADER_SIZE
mov [rel current_break], rbx
mov rsp, rbp ; return the function
pop rbp
ret
error:
mov rax, 0
mov rsp, rbp
pop rbp
ret
; END OF FUNCTION
;; deallocate ;;
; PURPOSE:
; The purpose of this function is to give back
; a region of memory to the pool after we’re done
; using it.
;
; PARAMETERS:
; The only parameter is the address of the memory
; we want to return to the memory pool.
;
; RETURN VALUE:
; There is no return value.
;
; PROCESSING:
; If you remember, we actually hand the program the
; start of the memory that they can use, which is
; 8 storage locations after the actual start of the
; memory region. All we have to do is go back
; 8 locations and mark that memory as available,
; so that the allocate function knows it can use it.
global deallocate
; Stack position of the memory region to free
ST_MEMORY_SEG equ 8
deallocate:
; since the function is so simple, we
; don’t need any of the fancy function stuff
; get the address of the memory to free
; (normally this is [rbp + 16], but since
; we didn’t push rbp or move rsp to
; rbp we can just do [rsp + 8])
mov rax, [rsp + ST_MEMORY_SEG]
; get the pointer to the real beginning of the memory
sub rax, HEADER_SIZE
; mark it as available
mov dword [rax + HDR_AVAIL_OFFSET], AVAILABLE
; return
ret
; END OF FUNCTION