-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnasmx.inc
executable file
·616 lines (554 loc) · 10.1 KB
/
nasmx.inc
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
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
%ifndef _NASMX_INC_
%define _NASMX_INC_
%ifidn __OUTPUT_FORMAT__,elf
%elifidn __OUTPUT_FORMAT__,elf32
%elifidn __OUTPUT_FORMAT__,elf64
%elifidn __OUTPUT_FORMAT__,win32
%define __UNDERSCORE__
%elifidn __OUTPUT_FORMAT__,win64
%define __UNDERSCORE__
%else
%define __CDECL_UNDERSCORE__
%define __UNDERSCORE__
%endif
%imacro IMPORT 1-2
%ifndef __imp_defined_%1
%if %0 = 1
%ifdef __CDECL_UNDERSCORE__
%define __cdecl_defined_%1 _%1
%define __imp_defined_%1 _%1
%else
%define __cdecl_defined_%1 %1
%define __imp_defined_%1 %1
%endif
%else
%ifdef __UNDERSCORE__
%define __imp_defined_%1 _%1@%2
%else
%define __imp_defined_%1 %1@%2
%endif
%endif
%else
%error Import symbol %1 has already been defined
%endif
%endmacro
%imacro INVOKE 1-100
%push invoke
%assign %$args 0
%assign %$arg_rot -1
%ifdef __imp_defined_%1
%ifndef __imp_declared_%1
EXTERN __imp_defined_%1
%define __imp_declared_%1 %1
%endif
%define __cur_import__
%define _proc __imp_defined_%1
%else
%define _proc %1
%endif
%ifidn __BITS__,64
%ifidn __OUTPUT_FORMAT__,win64
%ifdef __cur_import__
%assign %$arg_rot 1
%endif
push rsp
push QWORD[rsp]
and spl,BYTE 0xF0
%define %$arg_cur 0
%define %$arg_typ 0
%rep %0-1
%rotate %$arg_rot
%ifdef __cur_import__
%if %$args < 32
%if %$args == 0
%define %$arg_cur cx
%define %$arg_typ 1
%elif %$args == 8
%define %$arg_cur dx
%define %$arg_typ 1
%elif %$args == 16
%define %$arg_cur r8
%define %$arg_typ 2
%else
%define %$arg_cur r9
%define %$arg_typ 2
%endif
%ifnum %1
%if %1 == -1
%if %$arg_typ == 1
or r %+ %$arg_cur, %1
%else
or %$arg_cur, %1
%endif
%elif %1 == 0
%if %$arg_typ == 1
xor e %+ %$arg_cur,e %+ %$arg_cur
%else
xor %$arg_cur %+ d, %$arg_cur %+ d
%endif
%else
%if %1 > 2^32
%if %$arg_typ == 1
mov r %+ %$arg_cur, %1
%else
mov %$arg_cur, %1
%endif
%else
%if %$arg_typ == 1
mov e %+ %$arg_cur, %1
%else
mov %$arg_cur %+ d, %1
%endif
%endif
%endif
%else
%ifstr %1
jmp %%endstr_%$args
%%str_%$args: db %1, 0
%%endstr_%$args:
%if %$arg_typ == 1
lea r %+ %$arg_cur,[rel %%str_%$args]
%else
lea %$arg_cur,[rel %%str_%$args]
%endif
%else
%ifid %1
%if %$arg_typ == 1
lea r %+ %$arg_cur,[rel %1]
%else
lea %$arg_cur,[rel %1]
%endif
%else
%if %$arg_typ == 1
mov r %+ %$arg_cur,%1
%else
mov %$arg_cur,%1
%endif
%endif
%endif
%endif
%else
%ifstr %1
jmp %%endstr_%$args
%%str_%$args: db %1, 0
%%endstr_%$args:
push QWORD %%str_%$args
%else
push QWORD %1
%endif
%endif
%else
%ifstr %1
jmp %%endstr_%$args
%%str_%$args: db %1, 0
%%endstr_%$args:
push QWORD %%str_%$args
%else
push QWORD %1
%endif
%endif
%assign %$args %$args+8
%endrep
sub rsp,0x20
call _proc
%if %$args <> 0
%rotate %$arg_rot
%ifdef %1_defined
add rsp, %$args
%else
%ifdef __cur_import__
%if %$args > 32
add rsp,(0x28 + (%$args - 32))
%else
add rsp,0x28
%endif
%else
add rsp,(0x28 + %$args)
%endif
%endif
%else
%ifndef %1_defined
add rsp,0x28
%endif
%endif
pop rsp
%else
%error "Unsupported 64-bit INVOKE"
%endif
%else
%rep %0-1
%rotate %$arg_rot
%ifstr %1
jmp %%endstr_%$args
%%str_%$args: db %1, 0
%%endstr_%$args:
push dword %%str_%$args
%else
push dword %1
%endif
%assign %$args %$args+4
%endrep
call _proc
%if %$args <> 0
%rotate %$arg_rot
%ifdef __cdecl_defined_%1
add esp, %$args
%endif
%endif
%endif
%ifdef __cur_import__
%undef __cur_import__
%endif
%undef _proc
%pop
%endmacro
%imacro PROC 1-100
%push proc
%ifidn __BITS__,64
%assign %$arg 0x30
%else
%assign %$arg 8
%endif
%ifdef __entry_%1
%ifndef __PROCEDURE__
%ifdef __UNDERSCORE__
global _main
_main:
%else
global main
main:
%endif
%define __PROCEDURE__ _end_%1
%define _entry_
%define __leave_present__
%else
%error "missing endproc directive."
%endif
%else
%ifndef __PROCEDURE__
%1:
%ifidn __BITS__,64
push rbp
mov rbp, rsp
%else
push ebp
mov ebp, esp
%endif
%define __PROCEDURE__ _end_%1
%rep %0-1
%rotate 1
%1 argd
%endrep
%else
%error "missing endproc directive."
%endif
%endif
%endmacro
%imacro LOCALS 0
%assign %$locnt 0
%endmacro
%imacro LOCAL 1-2
%ifidni %2, qword
%assign %$locnt 8+%$locnt
%elifidni %2, dword
%assign %$locnt 4+%$locnt
%elifidni %2, word
%assign %$locnt 2+%$locnt
%elifidni %2, byte
%assign %$locnt 1+%$locnt
%endif
%1 EQU %$locnt
%endmacro
%imacro ENDLOCALS 0
%ifidn __BITS__,64
sub rsp, %$locnt
%else
sub esp, %$locnt
%endif
%endmacro
%imacro ARGD 0-1
%ifdef __PROCEDURE__
%00 equ %$arg
%if %0 = 1
%assign %$arg %1+%$arg
%else
%ifidn __BITS__,64
%assign %$arg 8+%$arg
%else
%assign %$arg 4+%$arg
%endif
%endif
%else
%error "arguments must be defined within a proc/endproc block."
%endif
%endmacro
%ifidn __BITS__,64
%idefine VAR(v) [rbp-v]
%idefine ARGV(v) [rbp+v] ;RCX/RDX/R8/R9...
%else
%idefine VAR(v) [ebp-v]
%idefine ARGV(v) [ebp+v]
%endif
%idefine OFFSET
%imacro ENDPROC 0
%ifdef __PROCEDURE__
__PROCEDURE__:
%ifndef _entry_
%pop
%else
%undef _entry_
%endif
%undef __PROCEDURE__
%else
%error "missing proc directive."
%endif
%endmacro
%imacro LEAVE 0
%ifndef __leave_present__
%define __leave_present__
%endif
%ifidn __BITS__,64
mov rsp, rbp
pop rbp
%else
mov esp, ebp
pop ebp
%endif
%endmacro
%imacro RET 0-1
%ifdef __PROCEDURE__
%ifndef __leave_present__
%ifctx proc
leave
ret %1
%undef __leave_present__
%else
ret %1
%endif
%else
ret %1
%undef __leave_present__
%endif
%else
ret
%endif
%endmacro
%imacro PROTO 1-2
%if %0 = 1
%ifdef __CDECL_UNDERSCORE__
global _%1
%else
global %1
%endif
%else
%ifdef __UNDERSCORE__
global _%1
%else
global %1
%endif
%endif
%endmacro
%imacro ENTRY 1
%ifdef __UNDERSCORE__
%define __entry_%1 _main
%else
%define __entry_%1 main
%endif
%endmacro
%imacro RJMP 2
; This macro preforms the opposite conditional jump
; than what the value suggests, it's used internally
; by other macros
%ifidni %1, ==
jne %2
%elifidni %1, >
jle %2
%elifidni %1, <
jge %2
%elifidni %1, >=
jl %2
%elifidni %1, <=
jg %2
%elifidni %1, !=
je %2
%elifidni %1, !>
jg %2
%elifidni %1, !<
jl %2
%elifidni %1, CARRY
jnc %2
%elifidni %1, BELOW
jnb %2
%elifidni %1, ABOVE
jna %2
%elifidni %1, PARITY
jnp %2
%elifidni %1, SIGNED
jns %2
%elifidni %1, OVERFLOW
jno %2
%elifidni %1, !CARRY
jc %2
%elifidni %1, !BELOW
jb %2
%elifidni %1, !ABOVE
ja %2
%elifidni %1, !PARITY
jp %2
%elifidni %1, !SIGNED
js %2
%elifidni %1, !OVERFLOW
jo %2
%endif
%endmacro
%imacro SJMP 2
%ifidni %1, ==
je %2
%elifidni %1, >
jg %2
%elifidni %1, <
jl %2
%elifidni %1, >=
jge %2
%elifidni %1, <=
jle %2
%elifidni %1, !=
jne %2
%elifidni %1, !>
jng %2
%elifidni %1, !<
jnl %2
%elifidni %1, CARRY
jc %2
%elifidni %1, BELOW
jb %2
%elifidni %1, ABOVE
ja %2
%elifidni %1, PARITY
jp %2
%elifidni %1, SIGNED
js %2
%elifidni %1, OVERFLOW
jo %2
%elifidni %1, !CARRY
jnc %2
%elifidni %1, !BELOW
jnb %2
%elifidni %1, !ABOVE
jna %2
%elifidni %1, !PARITY
jnp %2
%elifidni %1, !SIGNED
jns %2
%elifidni %1, !OVERFLOW
jno %2
%endif
%endmacro
%imacro BREAK 0
jmp %$break
%endmacro
%imacro IF 3
%push IF
%assign %$next 1
cmp %1, %3
RJMP %2, %$local_%$next
%endmacro
%imacro ELSIF 3
%ifctx IF
jmp %$endif
%$local_%$next:
%assign %$next 1+%$next
cmp %1, %3
RJMP %2, %$local_%$next
%else
%error "ELSIF directive must be within an IF block."
%endif
%endmacro
%imacro ELSE 0
%ifndef _else_
%ifctx IF
jmp %$endif
%$local_%$next:
%assign %$next 1+%$next
%define _else_
%else
%error "ELSE directive must be within an IF block."
%endif
%else
%error "There can only be one ELSE per IF block."
%endif
%endmacro
%imacro ENDIF 0
%ifctx IF
%ifndef _else_
%$local_%$next:
%else
%undef _else_
%endif
%$endif:
%pop
%else
%error "ENDIF directive must be within an IF block."
%endif
%endmacro
%imacro SWITCH 1
%push SWITCH
mov EDX, %1
%assign %$next 1
%endmacro
%imacro CASE 1
%ifctx SWITCH
%$local_%$next:
%assign %$next 1+%$next
%ifidn __BITS__,64
cmp rdx, %1
%else
cmp edx, %1
%endif
jnz near %$local_%$next
%else
%error "CASE directive must be within a SWITCH block."
%endif
%endmacro
%imacro DEFAULT 0
%ifctx SWITCH
%define _default_
%$local_%$next:
%else
%error "DEFAULT directive must be within a SWITCH block."
%endif
%endmacro
%imacro ENDSWITCH 0
%ifndef _default_
%$local_%$next:
%else
%undef _default_
%endif
%$break:
%pop
%endmacro
%imacro DO 0
%push DO
%$begin:
%endmacro
%imacro UNTIL 3
%ifctx DO
cmp %1, %3
RJMP %2, %$begin
%$break:
%else
%error "UNTIL directive must be preceded by DO."
%endif
%pop
%endmacro
%imacro WHILE 3
%ifctx DO
cmp %1, %3
SJMP %2, %$begin
%$break:
%else
%error "WHILE directive must be preceded by DO."
%endif
%pop
%endmacro
%endif ;NASMX_INC