-
Notifications
You must be signed in to change notification settings - Fork 8
/
asm.asm
225 lines (180 loc) · 5.7 KB
/
asm.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
format ELF64
section '.text' executable
public main
extrn malloc
extrn free
extrn clock
NUM_RECORDS = (50 * 1000 * 444)
TRADE_SIZE = 8 + 8 + 8 +4 +4 +8 +1 ;; add seven to this to get structs equivalent in layout to C's (padded structs_
ARRAY_BYTES = NUM_RECORDS * TRADE_SIZE
NUM_RUNS = 5
B = 66 ; 1000010
S = 83 ; 1010011
INIT_BUY_COST = 0
INIT_SELL_COST = 0
CLOCKS_PER_SEC = 1000000
CLOCKS_PER_MSEC = CLOCKS_PER_SEC/1000
main:
mov rdi, ARRAY_BYTES ;malloc the array in which to store the trades
call malloc
mov [ArrayStart], rax
mov r15, rax ;store &(trades[0]) in r15
mov r14, NUM_RUNS ;prepare the run counter
doRun:
sub r14, 1 ;reduce run counter by one
call clock ;rax = current clock in ticks
mov r8, rax ;store clock in r8
xor rax,rax ;clear rax
xor r11, r11
mov byte r11b, S ;store S in r11 for later use in cmov instruction
xor r12, r12 ;clear r12
mov rcx, r15 ;rcx = &(trades[0])
add rcx, ARRAY_BYTES ;rcx = &(trades[NUM_RECORDS])
mov rbx, NUM_RECORDS ;rbx = NUM_RECORDS
initTrades:
sub rcx, TRADE_SIZE ;rcx = &(trades[NUM_RECORDS - number of trades initialised])
sub rbx, 1 ;rbx -= 1
mov qword [rcx], rbx ;tradeId = rbx
mov qword [rcx+8], 1 ;clientId = 1
mov dword [rcx+16], 123 ;venueCode = 123
mov dword [rcx+20], 321 ;instrumentCode = 123
mov qword [rcx+24], rbx ;price = rbx
mov qword [rcx+32], rbx ;quantity = rbx
mov byte r12b, B ;r12b = B
and rbx, 1 ;if rbx is an even number, this will be zero
cmovnz r12, r11 ;if it's not zero, move S into r12
mov byte [rcx+40], r12b ;side = r12
cmp rcx, r15 ;if rcx != &(trades[0]), continue looping
jne initTrades
mov r9, INIT_BUY_COST ;buyCost = 0
mov r10, INIT_SELL_COST ;sellCost = 0
xor r12, r12 ;clear r12 for later use
mov rcx, r15 ;rcx = &(trades[0])
add rcx, ARRAY_BYTES ;rcx = &(trades[NUM_RECORDS])
countCosts:
sub rcx, TRADE_SIZE ;rcx = &(trades[NUM_RECORDS - number of trades counted])
mov qword rax, [rcx+24] ; store price in rax
mul qword [rcx + 32] ; multiply price by quantity, storing result in RDX
mov byte r12b, [rcx+40] ; store side in r12
and r12, 1 ;if r12 is B, this is zero, else if it is S, this is one
jnz addToSellCost ;if (trade->Side == 'B') {
add r9, rdx ;buyCost += trade->Price * trade->Quantity;
xor rdx, rdx ;clear rdx
addToSellCost: ;else if (trade->Side == 'S') {
add r10, rdx ;sellCost += trade->Price * trade->Quantity;
cmp rcx, r15 ;compare rcx to &(trades[NUM_RECORDS])
jne countCosts ;loop if countdown has not reached start of array
mov [rsp], r9 ;save buyCost in stack
mov [rsp+8], r10 ;save sellCost in stack
xor rax,rax ;clear rax
call clock ;store current time in tics in rax
sub rax, r8 ;rax = endTime - startTime;
xor rdx, rdx ;clear rdx
mov rbx, CLOCKS_PER_MSEC
div rbx ;convert elased tick time into milliseconds, store result in RAX
mov [rsp+16],rax ;store elapsed time in stack
mov rax, 1
mov rdi, 1
lea rsi, [printTime]
mov rdx, 9 ;size of printTime
syscall ;print "duration"
mov rax, [rsp+16]
call PRINTDEC ;print elapsed time
mov rax, 1
mov rdi, 1
lea rsi, [printMs]
mov rdx, 2 ;size of printMs
syscall ;print "ms"
mov rax, 1
mov rdi, 1
lea rsi, [printNL]
mov rdx, 1 ;size of printNL
syscall ;print newline
mov rax, 1
mov rdi, 1
lea rsi, [printRun]
mov rdx, 9 ;size of printRun
syscall ;print "Runnum = "
mov rax, r14
call PRINTDEC ;print runNum
mov rax, 1
mov rdi, 1
lea rsi, [printNL]
mov rdx, 1 ;size of printNL
syscall ;print newline
mov rax, 1
mov rdi, 1
lea rsi, [printBuy]
mov rdx, 10 ;size of printBuy
syscall ;print "buyCost = "
mov qword rax, [rsp]
call PRINTDEC ;print buyCost
mov rax, 1
mov rdi, 1
lea rsi, [printNL]
mov rdx, 1 ;size of printNL
syscall ;print newline
mov rax, 1
mov rdi, 1
lea rsi, [printSell]
mov rdx, 11 ;size of printSell
syscall ;print "sellCost = "
mov qword rax, [rsp+8]
call PRINTDEC ;print sellCost
mov rax, 1
mov rdi, 1
lea rsi, [printNL]
mov rdx, 1 ;size of printNL
syscall ;print newline
cmp r14, 0
jnz doRun ;if runcounter's not zero, run again
mov rdi, r15
call free ;free trade array
quit:
mov rax,60
mov rdi,0
syscall ;quit, returning zero
PRINTDEC: ;Number printing routine from stack overflow; http://stackoverflow.com/questions/17862664/printing-a-number-in-x86-64-assembly
LEA R9, [NUMBER + 22] ; last character of buffer
MOV R10, R9 ; copy the last character address
MOV RBX, 10 ; base10 divisor
DIV_BY_10:
XOR RDX, RDX ; zero rdx for div
DIV RBX ; rax:rdx = rax / rbx
ADD RDX, 0x30 ; convert binary digit to ascii
TEST RAX,RAX ; if rax == 0 exit DIV_BY_10
JZ LAST_REMAINDER
MOV byte [R9], DL ; save remainder
SUB R9, 1 ; decrement the buffer address
JMP DIV_BY_10
LAST_REMAINDER:
TEST DL, DL ; if DL (last remainder) != 0 add it to the buffer
JZ CHECK_BUFFER
MOV byte [R9], DL ; save remainder
SUB R9, 1 ; decrement the buffer address
CHECK_BUFFER:
CMP R9, R10 ; if the buffer has data print it
JNE PRINT_BUFFER
MOV byte [R9], '0' ; place the default zero into the empty buffer
SUB R9, 1
PRINT_BUFFER:
ADD R9, 1 ; address of last digit saved to buffer
SUB R10, R9 ; end address minus start address
ADD R10, 1 ; R10 = length of number
MOV RAX, 1 ; NR_write
MOV RDI, 1 ; stdout
MOV RSI, R9 ; number buffer address
MOV RDX, R10 ; string length
SYSCALL
RET
section '.data' writeable
printBuy db "buyCost = "
printSell db "sellCost = "
printRun db "runNum = "
printTime db "duration "
printMs db "ms"
printNL db 0x0A
section '.bbs' writeable
ArrayStart rq 1
LETTER rb 1
NUMBER rb 23