-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuDlong.asm
231 lines (183 loc) · 5.57 KB
/
uDlong.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
SECTION .data
UDLONGLEN EQU 16
HEXDIGITS: db "0123456789ABCDEF"
HEXDIGITSLEN equ $-HEXDIGITS
SECTION .bss
BUFFLEN equ 33 ; we need 33 because 1 char needs 1 byte and 1 hex needs 4 bits
; +1 becaues of LF
BUFF resb BUFFLEN ; temp buffer to read hex value
SECTION .text
GLOBAL addition, subtraction, multiplication, readUDlong, writeUDlong, copyUDlong
; Adds number from RSI to RDI. Stores result in RDI.
; RDI = address of first summand
; RSI = address of second summand
addition:
push rax
mov rax, qword[rsi]
add qword[rdi], rax ; adds the first 8 bytes
mov rax, qword[rsi+8]
adc qword[rdi+8], rax ; adds the last 8 bytes with carry from before
; with 'jc label' here we could check if there is an overflow
pop rax
ret
; Subtracts number from RSI to RDI. Stores result in RDI.
; RDI = address of minuend
; RSI = address of subtrahend
subtraction:
push rax
mov rax, qword[rsi]
sub qword[rdi], rax ; subtracts the first 8 bytes
mov rax, qword[rsi+8]
sbb qword[rdi+8], rax ; subtracts the last 8 bytes with borrow from before
; with 'jc label' here we could check if there is an 'underflow'
pop rax
ret
; Multiply RDI with RSI. Stores result in RDI.
; RDI = address of first multiplier
; RSI = address of second multiplier
multiplication:
push r8
push r9
push rdx
push rax
mov r8, qword[rdi] ; frist block, first multiplier
mov r9, qword[rdi+8] ; second block, first multiplier
xor rdx, rdx ; clear RDX for mul
mov rax, r8
mul qword[rsi] ; multiply first 2 blocks
mov qword[rdi], rax ; move first result to first block
mov qword[rdi+8], rdx ; move overflow to second block
xor rdx, rdx ; clear RDX for mul
mov rax, r8
mul qword[rsi+8] ; multiply first block with second block
add qword[rdi+8], rax ; add first multiplication block
mov r10, rdx ; to calculate OF
xor rdx, rdx ; clear RDX for mul
mov rax, r9
mul qword[rsi] ; multiply second block with first block
add qword[rdi+8], rax ; add first multiplication block
jc .setOverFlowFlag ; set OF if carry is set from addition
or r10, rdx ; to calculate OF
cmp r10, 0 ; check if no overflow
jne .setOverFlowFlag ; set OF if overflow from mul
jmp $+2 ; no overflow, jump next 2 lines
.setOverFlowFlag:
sev ; set overflow flag
pop rax
pop rdx
pop r9
pop r8
ret
; Reads/writes hexstring into BUFF. Maxlength is BUFFLEN.
; %1 = 0 for read
; %1 = 1 for write
; Sets RBP as input length
%macro _readWriteUDlong 1
push rsi
push rdi
push rax
push rdx
mov rax, %1
mov rsi, BUFF
mov rdi, 1
mov rdx, BUFFLEN
syscall
mov rbp, rax
pop rdx
pop rax
pop rdi
pop rsi
%endmacro
; Converts string in register AL to its hex equavilent.
; AL = number to convert
%macro _stringToHex 0
cmp al, '0' ; if less than '0' end of string or invalid char
jl %%invalidChar ; jump to done
sub al, '0' ; sub '0' to convert 0-9
cmp al, 9 ; cmp 0-9
jle %%done ; jump to done
sub al, 7 ; else sub 7 to convert A-F
cmp al, 0Ah ; cmp A
jl %%invalidChar ; filter ASCII 3Ah-40h
cmp al, 0Fh ; cmp F
jle %%done ; jump to done
sub al, 32 ; else sub 32 to convert a-f
cmp al, 0Ah ; cmp A
jl %%invalidChar ; filter ASCII 5B-60
cmp al, 0Fh ; if less or equal than F
jle %%done ; jump to done
%%invalidChar: ; label for invalid character
mov al, 0 ; set 0 if invalid
%%done:
%endmacro
; Reads number from STDIN to address in RDI.
; RDI = address to read number to
readUDlong:
_readWriteUDlong 0 ; reads STDIN to BUFF
push rcx
push rdx
push rax
push rbx
mov rcx, rbp ; input loop
dec rcx ; string starts by 0
dec rcx ; to remove LF
xor rdx, rdx ; store loop
.stringLoop: ; loop over the string
xor rax, rax ; clear RAX
mov al, byte[BUFF+rcx-1] ; copy letter
_stringToHex ; convert char to hex
mov rbx, rax ; store hex value in BL
shl bl, 4 ; shift 4 for little endian
mov al, byte[BUFF+rcx] ; copy second letter
_stringToHex ; convert char to hex
or bl, al ; or BL (xxxx0000) with AL (0000xxxx)
mov [rdi+rdx], bl ; store BL to its position
inc rdx ; inc store position
dec rcx ; dec for first char
dec rcx ; dec for second char
cmp rcx, 0 ; compare RCX to 0
jns .stringLoop ; jump as long as it is not negative
pop rbx
pop rax
pop rdx
pop rcx
ret
; Writes number at address of RSI to STDOUT.
; RDI = address of number to write
writeUDlong:
push rcx
push rdx
push rax
push rbx
mov rcx, UDLONGLEN ; store loop
xor rdx, rdx ; output loop
.hexToString: ; loop to convert hex to string
xor rax, rax ; clear rax
mov al, byte[rdi+rcx-1] ; mov current number to AL
mov rbx, rax ; copy it for second nybble
and al, 0Fh ; mask out all but low nybble
mov al, byte[HEXDIGITS+rax] ; get character equivalent
mov byte[BUFF+rdx*2+1], al ; writes the number to its position
shr bl, 4 ; shift high 4 bits of char into low 4 bits
mov bl, byte[HEXDIGITS+rbx] ; get character equivalent
mov byte[BUFF+rdx*2], bl ; write the number to its position
inc rdx ; inc RDX for the next write iteration
loop .hexToString ; loop over the string
mov byte[BUFF+BUFFLEN-1], 10 ; add LF to the end
_readWriteUDlong 1 ; write the number to STDOUT
pop rbx
pop rax
pop rdx
pop rcx
ret
; Copy number from RDI to RSI.
; RDI = address of original number
; RSI = address of copy number
copyUDlong:
push rax
mov rax, qword[rdi] ; copy the first qword
mov qword[rsi], rax ; to qword[RSI]
mov rax, qword[rdi+8] ; copy the second qword
mov qword[rsi+8], rax ; to qword[RSI+8]
pop rax
ret