Paras
Paras

Reputation: 238

Assembly : How to convert data into Ascii

I have made a program to add the elements of an array in x64 assembly languge(nasm). But when I display the sum it shows some other unreadable result. So I enquired about it and I found that I need to convert the sum into ASCII format and then display it. But I am unable to figure out what this part of code do. I have embedded that part of code into my program and now it is working fine, but I am unable to understand what this piece of code actually do. Here is my program:

global _start

section .data
arr1 dq 0000000000000001h,0000000000000002h,0000000000000003h,0000000000000004h,0000000000000005h
carry db 00

msg1 db 'Addition Is:',10
len1 equ $-msg1
msg2 db  " "
len2 equ $-msg1

section .bss
addition resb 16

section .text
_start: 
mov cl,4
mov rsi,arr1
mov rax,[rsi]
up: add rsi,8
add rax,[rsi]
jnc a1
inc byte[carry]

a1:   dec cl
jnz up

call display            ;ASCII conversion procedure display called

mov rax,1
mov rdi,1
mov rsi,msg1
mov rdx,len1
syscall


add byte[carry],30h
mov rax,1
mov rdi,1
mov rsi,carry
mov rdx,1
syscall




mov rax,1
mov rdi,1
mov rsi,addition
mov rdx,16
syscall

mov rax,60
mov rdi,0
syscall

display:mov rdi,addition        ;How this procedure converts the addition into ASCII
    mov cl,16
up1:    rol rax,4
    mov rbx,rax
    and rax,0Fh
    cmp rax,09h
    ja dn1
    add rax,30h
    jmp dn
dn1:    add rax,37h
dn: mov [rdi],rax
    mov rax,rbx
    inc rdi
    dec cl
    jnz up1
    ret

Upvotes: 1

Views: 663

Answers (1)

Michael
Michael

Reputation: 58427

I've annotated the relevant parts of the code with comments that explains what is going on. I'm going to assume that you know how base16 arithmetic and bitwise logic works. If not, you're going to have to look that up on wikipedia or somewhere else.

    mov cl,16      ; The loop counter (there are 16 digits)
up1:    rol rax,4  ; Rotate the contents of rax 4 bits to the left. What were
                   ; previously the 4 most significant bits will now be in
                   ; the 4 least significant bits of rax. This is done because
                   ; we want to print the most significant digit first. 
    mov rbx,rax    ; Make a copy of the rotated version of rax.
    and rax,0Fh    ; Keep the 4 least significant bits of rax and set all other
                   ; bits of rax to 0.
    cmp rax,09h    ; rax will now be in the range 0..15. Is it greater than 9?
    ja dn1         ; ..if so, jump to dn1.
    add rax,30h    ; rax was in the range 0..9. The characters '0'..'9' are encoded as
                   ; 30h..39h in ASCII, so add 30h to convert into a character.
    jmp dn         ; We're done with this case.
dn1:    add rax,37h ; rax is in the range 10..15. The characters 'A'..'F' are encoded as
                    ; 41h..46h in ASCII, so add 37h to convert into a character.
dn: mov [rdi],rax  ; Store the character in the buffer pointed to by rdi.
    mov rax,rbx    ; Restore rax to the value it had right after the rol. So on the
                   ; next iteration we'll be processing what were originally the
                   ; second most significant 4 bits, and so on.
    inc rdi        ; Increment the buffer pointer.
    dec cl         ; Decrement the loop counter.
    jnz up1        ; Repeat for all 16 digits.

Upvotes: 1

Related Questions