Last active
September 19, 2017 05:07
-
-
Save SeijiEmery/7a4b8265fefa086e7b8164726071334a to your computer and use it in GitHub Desktop.
sketch for macro-assembler with lisp syntax and builtin testcases, may build this at some point (yes, I'm a bit nuts)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ; | |
| ; Would be neat to have enumerable enums like this: | |
| ; | |
| (enum colors | |
| (red 0xff0000ff) | |
| (green 0x00ff00ff) | |
| (blue 0x0000ffff) | |
| (alpha 0x000000ff)) | |
| ; | |
| ; BSD, x86_64 syscalls | |
| ; | |
| (proc exit | |
| (params | |
| (in rdi rv) | |
| (local rax _) | |
| ) | |
| (body | |
| (mov rax SYSCALL_EXIT) | |
| (syscall) | |
| ) | |
| ) | |
| (proc write | |
| (params | |
| (in rdi fd) | |
| (in rsi buffer) | |
| (in rdx length) | |
| (local rax _) | |
| ) | |
| (body | |
| (mov rax SYSCALL_WRITE) | |
| (syscall) | |
| ) | |
| ) | |
| (proc read | |
| (params | |
| (in rdi fd) | |
| (in rsi buffer) | |
| (in rdx length) | |
| (local rax _) | |
| ) | |
| (body | |
| (mov rax SYSCALL_READ) | |
| (syscall) | |
| ) | |
| ) | |
| ; | |
| ; A few string algorithms | |
| ; | |
| (proc strncpy | |
| (params | |
| (in rsi src) | |
| (in rdi dst) | |
| (in rcx len) | |
| (local rax _) | |
| ) | |
| (body | |
| ; Zero-length case | |
| (test len len) | |
| (jz end) | |
| (clear rax) | |
| (label top) | |
| ; If --len == 0, return | |
| (dec len) | |
| (jl end) | |
| ; If *src == 0, return | |
| (mov al [src]) | |
| (test al al) | |
| (jz end) | |
| ; Copy byte, and repeat | |
| (mov [dst] al) | |
| (inc src) | |
| (inc dst) | |
| (jmp top) | |
| (label end) | |
| ) | |
| ) | |
| (proc memcmp | |
| (params | |
| (in rsi s1) | |
| (in rdi s2) | |
| (in rcx len) ; Must be (min (length-of-bytes s1) (length-of-bytes s2)) | |
| (out flags result) | |
| ) | |
| (body | |
| (cld) | |
| (cmp rcx, rcx) | |
| (repe cmpsb) | |
| ) | |
| (tests | |
| (should-compare-equal | |
| (data-array i8 first (1 2 3 4 5 6 7)) | |
| (data-array i8 second (1 2 3 4 5 6 7)) | |
| (call-proc memcmp (s1 first) (s2 second) (len (length-of-bytes first))) | |
| (require-flags z) | |
| ) | |
| (should-compare-less | |
| (data-array i8 first (1 2 3 4 4 6 7)) | |
| (data-array i8 second (1 2 3 4 5 6 7)) | |
| (call-proc memcmp (s1 first) (s2 second) (len (length-of-bytes first))) | |
| (require-flags l) | |
| ) | |
| (should-compare-greater | |
| (data-array i8 first (1 2 3 4 5 6 7)) | |
| (data-array i8 second (1 2 3 4 4 6 7)) | |
| (call-proc memcmp (s1 first) (s2 second) (len (length-of-bytes first))) | |
| (require-flags g) | |
| ) | |
| (should-handle-single-byte | |
| (data-array i8 first (1)) | |
| (data-array i8 second (2)) | |
| (call-proc memcmp (s1 first) (s2 second) (len (length-of-bytes first))) | |
| (require-flags g) | |
| ) | |
| (should-handle-zero | |
| (call-proc memcmp (s1 0) (s2 0) (len 0)) | |
| (require-flags z) | |
| ) | |
| (should-handle-zero-1 | |
| (data-array i8 first (1 2 3 4 5 6 7)) | |
| (call-proc memcmp (s1 first) (s2 0) (len 0)) | |
| (require-flags z) | |
| ) | |
| (should-handle-zero-2 | |
| (data-array i8 first (1 2 3 4 5 6 7)) | |
| (call-proc memcmp (s1 0) (s2 first) (len 0)) | |
| (require-flags z) | |
| ) | |
| ) | |
| ) | |
| ; Writes digits of an unsigned 64-bit value as to a buffer. | |
| ; Can write decimal binary (base 2), (base 10), hexadecimal (base 16), etc. | |
| ; Uses '0'-'9' for base 2-10, 'A'-'Z' for base 11-36. Base 37+ is undefined. | |
| (proc write-uint | |
| (params | |
| (in rax value) | |
| (in rbx base (default 10)) | |
| (inout rdi buffer (require non-null)) | |
| (inout rcx length (require non-zero)) | |
| (local rdx digit) | |
| ) | |
| (body | |
| ; save original length | |
| (push length) | |
| ; save TOS | |
| (push rbp) | |
| (mov rbp rsp) | |
| ; Write digits to buffer (stack memory, reversed) | |
| (label write-digits) | |
| ; Divide rax by base, convert remainder (rdx) to ascii digit | |
| (clear rdx) | |
| (idiv base) | |
| (add digit 0x30) ; add 0x30 to convert to ascii '0'-'9' (0x30-0x39) | |
| (cmp digit 0x39) ; if >= '9', convert to ascii 'A'-'Z' (0x41-0x5A) | |
| (if-g (add digit 8)) | |
| ; Save digit to stack memory | |
| (mov [rsp] digit) | |
| (dec rsp) | |
| (test value value) | |
| (jnz write-digits) | |
| ; calculate # digits written in rdx | |
| (mov rdx rsp) | |
| (sub rdx rbp) | |
| ; calculate rdx = min(length, rdx) | |
| (cmp rdx length) | |
| (cmovg rdx length) | |
| ; digits written backwards, but stack grows backwards | |
| ; => can now just memcpy from stack memory | |
| (inline-proc memcpy (src rsp) (dst buffer) (length rdx)) | |
| ; restore stack + original length | |
| (mov rsp rbp) | |
| (pop rbp) | |
| (pop length) | |
| ; update buffer + length values to point to end of written value | |
| (add buffer rdx) | |
| (sub length rdx) | |
| ) | |
| (tests | |
| ; TODO: check operating correctly, check for buffer overflows, edge cases, etc. | |
| ) | |
| ) | |
| ; Writes digits of a signed 64-bit value as to a buffer. | |
| ; Can write binary (base 2), decimal (base 10), hexadecimal (base 16), etc. | |
| ; Uses '0'-'9' for base 2-10, 'A'-'Z' for base 11-36. Base 37+ is undefined. | |
| (proc write-int | |
| (params | |
| (in rax value) | |
| (in rbx base (default 10)) | |
| (inout rdi buffer (require non-null)) | |
| (inout rcx length (require non-zero)) | |
| ) | |
| (body | |
| (cmp value 0) | |
| (if-z ; if value == 0 (special case) | |
| (mov [buffer] byte '0') | |
| (inc buffer) | |
| (dec length) | |
| (jmp end) | |
| ) | |
| (if-l ; if value < 0 (negative case) | |
| (neg value) ; make value positive | |
| (require-gt value 0) ; assert(value > 0) | |
| ; write '-' | |
| (mov [buffer] byte '-') | |
| (inc buffer) | |
| (dec length) | |
| ; stop iff we cannot write any more bytes (length MAY be zero) | |
| (jz end) | |
| ) | |
| (inline-proc write-uint (value value) (base base) (buffer buffer) (length length)) | |
| (label end) | |
| ) | |
| (tests | |
| ; TODO: check operating correctly, check for buffer overflows, edge cases, etc. | |
| ) | |
| ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment