%ifndef DTOS_INC %define DTOS_INC %ifndef MONAD_INC %include "monad.inc" %endif ;; TODO: Thread safety, allocate the write buffer instead of a global state incase it is interrupted and rewritten section .data _NUMERALS db "0123456789ABCDEF" _DATA_BYTE_BUFFER times 63 db "0" _FIRST_DIGIT db "0", 0x0A, 0 m_make DTOS_RESULT, _DATA_BYTE_BUFFER %macro dtomz_h 1 %if "%1" != "%rax" mov rax, %1 %endif mov rcx, 16 call data_to_zstring %endm %macro dtomz_d 1 %if "%1" != "%rax" mov rax, %1 %endif mov rcx, 10 call data_to_zstring %endm %macro dtomz_o 1 %if "%1" != "%rax" mov rax, %1 %endif mov rcx, 8 call data_to_zstring %endm %macro dtomz_b 1 %if "%1" != "%rax" mov rax, %1 %endif mov rcx, 2 call data_to_zstring %endm section .text clear_data_zstring: push rbp mov rbp, rsp push rdi cld lea rdi, [rel _DATA_BYTE_BUFFER] mov al, "0" mov rcx, 64 rep stosb std pop rdi mov rsp, rbp pop rbp ret data_to_zstring: ;; rax: Value ;; rcx: Base push rbp mov rbp, rsp ;; push rax push rcx call clear_data_zstring pop rcx pop rax cmp rcx, 16 ja .err_exit cmp rcx, 2 jb .err_exit std ;; Preserve Caller-saved registers push rsi push rdi ;; Initially include newline character lea rdi, [rel _FIRST_DIGIT] .loop: ;; Get lowest digit xor rdx, rdx div rcx ;; Set the numeral lea rsi, [rel _NUMERALS] add rsi, rdx movsb cmp rax, 0 jne .loop mov rax, rdi inc rax cld ;; Recover Registers pop rdi pop rsi m_return rel m_DTOS_RESULT, rax jmp .exit .err_exit: m_Nothing rel m_DTOS_RESULT .exit: lea rax, [rel m_DTOS_RESULT] ;; mov rsp, rbp pop rbp ret ;; Monadic functions (m_bind d2zs_m?) ;; data_to_zstring_m? ;; rax -> M (d2zs_? rax) data_to_zstring_mh: mov rcx, 16 call data_to_zstring ret data_to_zstring_md: mov rcx, 10 call data_to_zstring ret data_to_zstring_mo: mov rcx, 8 call data_to_zstring ret data_to_zstring_mb: mov rcx, 2 call data_to_zstring ret %endif