; Name:         bits128tooctal.asm
;
; Build:        nasm -felf64 -o bits128tooctal.o bits128tooctal.asm
;               ld -s -melf_x86_64 -o bits128tooctal bits128tooctal.o
;
; Description:  Convert a 128 bit unsigned integer in RDX:RAX to octal ASCII.
;               IN  : RDX:RAX is number to convert
;                     RDI : pointer to a 43 bytes long buffer
;               OUT : RDI contains the converted octal in ASCII notation
;
; To-do : optimize if RDX should be all zeros (32 bits numbers)
;         check number of leading zeros for lower bits conversions

bits 64

[list -]
     %include "unistd.inc"
[list +]

section .bss
     buffer:   resb   43
     eol:      resb   1
    
section .data

     msg:       db  "conversion to octal of 0x0123456789ABCDEF0123456789ABCDEF...", 10
     .length:   equ $-msg
     
section .text
     global _start
_start:        
     syscall    write, stdout, msg, msg.length
     mov        rax, 0x0123456789ABCDEF
     mov        rdx, 0x0123456789ABCDEF
     mov        rdi, buffer
     call       Bits128ToOctal
     mov        byte [eol], 0x0A
     mov        rsi, buffer
     mov        rdx, 43+1
     mov        rcx, 43
.repeat:
     lodsb
     cmp        al, "0"
     jne        .write
     dec        rdx
     loop       .repeat
.write:
     dec        rsi
     syscall    write, stdout
     syscall    exit, 0

Bits128ToOctal:
     push       rax
     push       rcx
     push       rdx
     push       rdi
     push       r8
     pushfq
     clc
     cld
     mov        r8, rax                 ; lowest 64 bits in R8    
     mov        rcx, 43                 ; 43 octals to do, first octal takes first two bits
.repeat:
     xor        al, al          
     cmp        rcx, 42                 ; first two done
     jg         .skip                   ; no, do them first
     rcl        r8, 1
     rcl        rdx, 1
     rcl        al, 1
.skip:    
     rcl        r8, 1
     rcl        rdx, 1
     rcl        al, 1
     rcl        r8, 1
     rcl        rdx, 1
     rcl        al, 1
     add        al,"0"                  ; make ASCII
     stosb
     loop       .repeat

     popfq
     pop        r8
     pop        rdi
     pop        rdx
     pop        rcx
     pop        rax
     ret