-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathitoa.s
162 lines (121 loc) · 2.71 KB
/
itoa.s
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
.intel_syntax noprefix
.global itoa
.type itoa, @function
itoa:
# char* itoa(int, char*, int UNUSED)
# rdi: int
# rsi: char*
# rax: char* (ret, points to same place as arg1 at beginning)
sub rsp, 8
mov [rsp], rbp
mov rbp, rsp
# rbx used, so prior val must be saved
sub rsp, 8
mov [rsp], rbx
xor rax, rax
mov rbx, rsi # temp hold init pointer
cmp rdi, 0
je itoa_zero
mov rax, rdi
mov rcx, 10 # to div by to get lsd from rax
l1_itoa:
xor rdx, rdx # to store remainder from div
div rcx # rax storing quotient, rdx storing remainder
add dl, 0x30 # '0'
mov byte ptr [rsi], dl
inc rsi
test rax, rax
jnz l1_itoa
rev:
# Null-terminate for strrev to work
mov byte ptr [rsi], 0x0
# no longer need to save registers
# after strrev, rax is only important
mov rdi, rbx
call strrev
jmp end_itoa
itoa_zero:
mov byte ptr [rsi], 0x30 # '0'
inc rsi
# Null-terminate
mov byte ptr [rsi], 0x0
mov rax, rbx
end_itoa:
mov rsp, rbp
mov rbp, [rsp]
add rsp, 8
ret
strrev:
# strrev(char*)
# rdi: char*
# rax: char* (ret)
sub rsp, 8
mov [rsp], rbp
mov rbp, rsp
# using rbx, so must save prior to using it
sub rsp, 8
mov [rsp], rbx
# arg0 already set
call _strlen
mov rcx, rax # storing length of str
# rdi contains pointer to end
# I have no idea what this is for but must be done to work properly
mov rsi, rdi
dec rsi
sub rdi, rcx
mov rax, rdi
# rax contains pointer to beginning to return
# rdi contains pointer from left hand side
# rsi contains pointer from right hand side
cmp rdi, rsi
# in case rdi pointer passed or equals to rsi pointer
# no need to reverse anymore
jge end_strrev
strrev_l:
mov bl, byte ptr [rdi]
mov cl, byte ptr [rsi]
mov byte ptr [rdi], cl
mov byte ptr [rsi], bl
inc rdi
dec rsi
cmp rdi, rsi
# in case rdi is still less than rsi, keep going when it's not (rdi >= rsi), fall to end
jl strrev_l
end_strrev:
# input str is assumed to be null-terminated so no null-termination needed
# restore rbx
lea rbx, [rsp]
add rsp, 8
mov rsp, rbp
mov rbp, [rsp]
add rsp, 8
ret
_strlen:
# int strlen(char*)
# rdi: char*
# rax: int (ret)
# str is assumed to be null-terminated
# null-char not accounted for in len
sub rsp, 8
mov [rsp], rbp
mov rbp, rsp
# using rbx, so save it
sub rsp, 8
mov [rsp], rbx
xor rax, rax
mov bl, byte ptr [rdi]
cmp bl, 0x0
je end_strlen
strlen_l:
inc rax
inc rdi
mov bl, byte ptr [rdi]
cmp bl, 0x0
jne strlen_l
end_strlen:
lea rbx, [rsp]
add rsp, 8
mov rsp, rbp
mov rbp, [rsp]
add rsp, 8
ret