Page 1 of 1

NASM/Linux - Converting Integer to Binary String

#1 GunnerInc  Icon User is offline

  • "Hurry up and wait"
  • member icon




Reputation: 858
  • View blog
  • Posts: 2,282
  • Joined: 28-March 11

Post icon  Posted 31 March 2014 - 09:07 PM

So you want to display a number as a Binary String? Well, lucky for us, the CPU only understands and deals with Binary numbers (Everything is Binary in the CPU, Letters, Numbers, Strings, etc..). In this example, I will use the number 89, in Binary that is 01011001 which is also the ASCII Code for the letter "Y".

We need a buffer large enough to hold the Binary ASCII String + a Carrage Return (ASCII 10), since we will be converting an 8-bit number, a 9 byte buffer will be large enough.

Next, we need to set our loop counter to TOTAL_BITS_OF_NUMBER - 1, in this case 7 (8-bit number - 1).
Next, we need a way to test each bit (There are many ways to do this), we will use SHL (Shift Left) to move each bit into the Carry Register and decide what to do from there. We can jump to a label and move a "0" or "1" into our buffer depening on what is in the Carry Flag, or we can use SETcc (Set bit on Condition), we will use SETC (Set bit if Carry). This instruction will set a bit to 1 if carry flag has a one, 0 otherwise. We then add ASCII 0 ("0") to this bit, increment our pointer, and decrement our loop counter and loop back for the next bit if counter is not -1.

SHL is destructive, meaning for every MSB you shift into the Carry Flag, the LSB gets replaced with a 0.

global main
sys_write   equ     1
sys_exit    equ     60
stdout      equ     0

section .data
fmtint  db  "%ld", 10, 0

section .bss
Num         resb    9

section .text
main:

    mov     rsi, 89
    mov     rdi, Num
    call    IntToBin8

    mov     rdx, rax
    mov     rsi, Num
    mov     rdi, stdout
    mov     rax, sys_write
    syscall

    mov     rdi, 0
    mov     rax, sys_exit
    syscall 

IntToBin8:
    mov     rcx, 7
    mov     rdx, rdi
    
.NextNibble:
    shl     sil, 1
    setc    byte [rdi]
    add     byte [rdi], "0"
    add     rdi, 1
    sub     rcx, 1
    jns     .NextNibble    

    mov     byte [rdi], 10
    
    mov     rax, rdi
    sub     rax, rdx
    inc     rax
    ret


IntToBin8:
    mov     rcx, 7
    mov     rdx, rdi

Here we set out loop counter RCX to 7 (TOTAL_BITS_OF_NUMBER - 1)
Next, we save the address of our buffer into RDX to hold the Binary ASCII.

.NextNibble:
    shl     sil, 1
    setc    byte [rdi]
    add     byte [rdi], "0"
    add     rdi, 1
    sub     rcx, 1
    jns     .NextNibble 

1. Shift a bit into the Carry Flag
2. If carry flag = 1 set byte to 1 at pointer in RDI, otherwhise set to 0
3. Add ASCII "0" (48) to this byte to convet to an ASCII number
4. Add 1 to our buffer pointer to increment it
5. Subtract 1 from our loop counter
6. If sign flag is not set (RCX != -1) loop back to .NextNibble for the next bit

    mov     byte [rdi], 10
    
    mov     rax, rdi
    sub     rax, rdx
    inc     rax
    ret

1. Now that our loop is done, move a LineFeed into out buffer.
2. Move the current pointer address into RAX
3. Subract the original pointer address (RDX) from the current pointer address, then increment it by one to return the number of bytes in out buffer.

Attached Image

This is what the SHL looks like:


For you to do:
How would you add spaces to the output so 01011001 would become 0101 1001?

Is This A Good Question/Topic? 0
  • +

Page 1 of 1