Printing binary string in assembly I'm writing a program to print binary string of a hardcoded word. Here is how it looks like currently:

main.asm

section .text
    global _start
    extern _print_binary_content

_start:
    push word [word_to_print] ; pushing word. Can we push just one byte?
    call _print_binary_content

    mov rax, 60
    mov rdi, 0
    syscall

section .data
    word_to_print: dw 0xAB0F


printer.asm

SYS_BRK_NUM equ 0x0C
BITS_IN_WORD equ 0x10
SYS_WRITE_NUM equ 0x01
STD_OUT_FD equ 0x01
FIRST_BIT_BIT_MASK equ 0x01
ASCII_NUMBER_OFFSET equ 0x30

section .text
    global _print_binary_content

_print_binary_content:
    pop rbp

    xor ecx, ecx ;zeroing rcx
    xor ebx, ebx ;zeroing rbx
    pop bx  ;the word to print the binary content of

    ;sys_brk for current location
    mov rax, SYS_BRK_NUM
    mov rdi, 0
    syscall
    ;end sys_brk

    mov r12, rax ;save the current brake location

    ;sys_brk for memory allocation 16 bytes
    lea rdi, [rax + BITS_IN_WORD]
    mov rax, SYS_BRK_NUM
    syscall
    ;end sys_brk

    xor ecx, ecx
    mov cl, byte BITS_IN_WORD - 1; used as a counter in the loop below

    loop:
        mov dx, bx
        and dx, FIRST_BIT_BIT_MASK
        add dx, ASCII_NUMBER_OFFSET
        mov [r12 + rcx], dl
        shr bx, 0x01
        dec cl
        cmp cl, 0
        jge loop

    mov rsi, r12
    mov rax, SYS_WRITE_NUM
    mov rdi, STD_OUT_FD
    mov rdx, BITS_IN_WORD
    syscall

    push rbp ; pushing return address back
    ret


If I compile link and run this program it works. But the question is about performance and maybe conventions of writing assembly programs. In the file printer.asm I cleaned ecx twice which looks kind of not optimal. Maybe some registers were used not by their purpose (I used intel-manual).

Can you please help me to improve this very simple program?
Low level programming is as much about optimization as it is legibility.
As you've noted, yours works, but I'd like to inject a few of my personal preferences here.

_start:

    ; Grab a buffer from stack suitably large enough to convert a 64 bit number

        push    rbp
        mov     rpb, rsp
        sub     rsp, 64                 ; Always keep RSP at least DWORD aligned


I prefer to keep functions distinct. Even though encorporating print into the conversion function
is doable, but maybe this conversion code could be used somewhere that printing isn't required.

        mov     esi, Value              ; Establish pointer to 16 bit value
        mov     rdi, rbp                ; Point to end of ASCII buffer
        call    Bin2Asc                 ; Return a pointer in RSI and characters in RDX


To accomodate SYSCALLs, have the function return values in register(s) that will be required. 

        mov     eax, SYS_WRITE
        syscall

        leave                           ; Kill procedure frame
        xor     eax, eax
        mov     edi, eax
        mov      cl, SYS_EXIT
        syscall


NOTE: A lot of times I'm using 32 bit registers and that is because I'm taking advantage of
processors sign extension mechanism, where some instruction sign extend into 64 bits.

Bin2Asc:

        xor     eax, eax                ; Clear accum
        mov     edx, eax                ; EDX is what SYS_WRITE is going to need
        lodsw
        std                             ; Change direction so buffer is populated in reverse

  .L0:  push    rax
        and      al, 1                  ; Isolate bit
        xor      al, '0'                ; Convert to "0" or "1"
        stosb                           ; Write to buffer
        inc      dl                     ; Bump character cound
        pop     rax
        shr     eax, 1                  ; Until RAX = 0
        jnz     .L0

        cld                             ; Reset direction flag
        inc     edi                     ; Point back to first character
        ret


Might this code have ERRORS, it may very well have, but as I'm not doing it on a Linux box and
I usually like to check my work, but it does demonstrate a concept that is optimized at least a bit.