Skip to content

Instantly share code, notes, and snippets.

@Trinitek
Last active March 27, 2017 06:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Trinitek/268dc4a56cb08dea7a1e to your computer and use it in GitHub Desktop.
Save Trinitek/268dc4a56cb08dea7a1e to your computer and use it in GitHub Desktop.
format PE64 console
entry start
include 'win64a.inc'
section '.text' code readable executable
start:
and rsp, -16
stdcall dotProduct, vA, vB
invoke printf, msg_num, rax
stdcall dotProduct, vA, vC
invoke printf, msg_num, rax
invoke ExitProcess, 0
proc dotProduct vectorA, vectorB
mov rax, [rcx]
cmp rax, [rdx]
je .calculate
invoke printf, msg_sizeMismatch
mov rax, 0
ret
.calculate:
mov r8, rcx
add r8, 8
mov r9, rdx
add r9, 8
mov rcx, rax
mov rax, 0
mov rdx, 0
.next:
mov rbx, [r9]
imul rbx, [r8]
add rax, rbx
add r8, 8
add r9, 8
loop .next
ret
endp
section '.data' data readable
msg_num db "%d", 0x0D, 0x0A, 0
msg_sizeMismatch db "Size mismatch; can't calculate.", 0x0D, 0x0A, 0
struc Vector [symbols] {
common
.length dq (.end - .symbols) / 8
.symbols dq symbols
.end:
}
vA Vector 1, 3, -5
vB Vector 4, -2, -1
vC Vector 7, 2, 9, 0
section '.idata' import data readable writeable
library kernel32, 'KERNEL32.DLL',\
msvcrt, 'MSVCRT.DLL'
include 'api/kernel32.inc'
import msvcrt,\
printf, 'printf'
format PE64 console ; We specify this executable as a 64-bit PE, and assign it a console instance for standard I/O (alternative is 'GUI')
entry start ; Entry point is the 'start' label, a few lines ahead
include 'win64a.inc' ; Includes 'stdcall', 'invoke', and 'proc' macros for calling and defining functions
section '.text' code readable executable
start:
and rsp, -16 ; Fix any stack alignment issues -- the stack must align to a 16-byte boundary
stdcall dotProduct, vA, vB ; Calls the dotProduct function using the 'fastcall' calling convention (stdcall is an alias to fastcall when targeting 64-bit)
invoke printf, msg_num, rax ; Calls the printf function using the 'fastcall' calling convention
;
stdcall dotProduct, vA, vC ; The difference between invoke and stdcall is that invoke first dereferences the pointer to the function before performing an stdcall
invoke printf, msg_num, rax ; ... This is necessary for imported functions such as printf, here
invoke ExitProcess, 0 ; Win32 ExitProcess call, with an exit code of 0
proc dotProduct vectorA, vectorB ; The fastcall convention puts the first arg in rcx, and the second in rdx
mov rax, [rcx] ; rax <- dereferenced ptr to vectorA, which returns the first QWORD, which is the size of the vector object (see struc below)
cmp rax, [rdx] ; compare vectorA.length to vectorB.length --- we dereferenced vectorA because we can only dereference ONE ptr at a time
je .calculate ; If the lengths are equal (if 'equal' flag in EFLAGS is set) then jump to '.calculate'
invoke printf, msg_sizeMismatch ; Else, print size mismatch message
mov rax, 0 ; rax (return value) <- 0
ret ; Return from function
.calculate:
mov r8, rcx ; Relocate rcx (ptr to vectorA) to r8 -- we will need rcx for the upcoming loop
add r8, 8 ; vectorA ptr now points to the first element
mov r9, rdx ; Relocate rdx (ptr to vectorB) to r9
add r9, 8 ; vectorB ptr now points to the first element
mov rcx, rax ; rcx <- rax (the number of elements in vectorA, A.K.A. vectorA.length -- see above)
mov rax, 0 ; clear rax -- this will hold our running total
mov rdx, 0 ; clear rdx -- cleared for no reason (?)
.next:
mov rbx, [r9] ; rbx <- the element pointed at by the vectorB ptr
imul rbx, [r8] ; unsigned multiply -- rbx <- rbx * the element pointed at by the vectorA ptr
add rax, rbx ; rax (running total) += rbx (multiplication result)
add r8, 8 ; vectorA ptr now points to next element
add r9, 8 ; vectorB ptr now points to next element
loop .next ; RCX--, then goto .next if RCX != 0
ret ; Return from function
endp ; End of function definition
section '.data' data readable
msg_num db "%d", 0x0D, 0x0A, 0
msg_sizeMismatch db "Size mismatch; can't calculate.", 0x0D, 0x0A, 0
; This is a special macro that defines a variable length structure, and is roughly the equivalent to this C struct:
;
; struct Vector {
; uint64_t length;
; uint64_t element1;
; uint64_t element2;
; uint64_t element3;
; uint64_t element4;
; uint64_t element5;
; ...
; uint64_t elementN;
; }
;
; Thus, the following...
;
; vA Vector 1, 3, -5
;
; ...creates a struct with the following values:
;
; vA.length == '3' ((QWORD) three elements in this vector)
; vA.symbols == 'dq 1, 3, -5' ((also QWORDs) three QWORDS defined one after another)
;
; And thus, in memory, the final structure will appear as such:
;
; dq 3, 1, 3, -5
struc Vector [symbols] {
common
.length dq (.end - .symbols) / 8
.symbols dq symbols
.end:
}
vA Vector 1, 3, -5 ; dq 3, 1, 3, -5
vB Vector 4, -2, -1 ; dq 3, 4, -2, -1
vC Vector 7, 2, 9, 0 ; dq 4, 7, 2, 9, 0
section '.idata' import data readable writeable
library kernel32, 'KERNEL32.DLL',\ ; DLL that contains ExitProcess
msvcrt, 'MSVCRT.DLL' ; DLL that contains printf
include 'api/kernel32.inc' ; FASM-provided include file that defines ExitProcess
import msvcrt,\ ; Declare that we want to import some functions from MSVCRT...
printf, 'printf' ; ...import 'printf', and refer to it as 'printf' in our code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment