'Output array of binary digits as a decimal number in NASM

I have a program that can add two arrays of binary numbers

I'm sorry, I'm not very good at asm

I can draw the conclusion myself, but to understand how to convert an array to a number, I don’t really understand how to do it

example:

section .text
global _start
_start:
    mov esi, 0
    mov ecx, len_arr_1

_add_two_array:

    mov eax, 0
    add al, [array_1 + esi]
    add al, [array_2 + esi]
    inc esi
    mov [res + esi], ax
    loop _add_two_array

mov esi, len_res - 1

_check:
    Call update

    dec esi
    cmp esi, -1
    jne _check
    jmp output_set

update:
    mov ebx, 2
    cmp [res + esi], bl 
    jge return

    ret
    
return:

    sub [res + esi], bl
    mov ebx, 1
    add [res + esi - 1], bl
    ret

output_set:
    mov esi, 0
    mov ecx, len_res

output:

    push ecx
    
    mov ecx, [res + esi]
    inc esi
    add ecx, 48
    mov [msg], ecx
    mov edx, msg_len
    mov ecx, msg
    mov ebx, 1
    mov eax, 4
    int 0x80

pop ecx

    loop output

exit:
    nop
    mov eax, 1
    mov ebx, 0
    int 80H

section .data

array_1 db 1, 1, 0
len_arr_1 equ $ - array_1

array_2 db 0, 1, 1
len_arr_2 equ $ - array_2

res db 0, 0, 0, 0
len_res equ $ - res

msg db '', 0xa
msg_len equ $ - msg
```

output: 1010 // need 10

how to display the resulting answer by converting it to a decimal number?



Solution 1:[1]

You throw un-commented asm code at us without any description what with what and how it does or does not. Most of us will not bother to look further.

You should clarify for example what your array represents Is it bigint or something else? like fixed point, floating point ... Is it MSB first or last?

Here few things I noticed just by quick look without any deeper analysis (Assuming unsigned "big" int):

  1. I do not see any carry propagation during long num addition

    Only the first addition (lowest bit/word) should use add and all others should be adc !!! or all are adc if you clear carry flag before addition loop.

  2. your input is array of BYTEs and output is array of WORDs ?

    That makes no sense and even if it is then you inconsistently update esi as you use it for both BYTEs and WORDs at the same time while incrementing only by 1. If not then your target digits overlap as you write ax so depending on MSB first/last order you might overwrite already computed digits...

  3. Your test case is wrong due to previous bullets !!!

    You know 110b + 011b = 1001b however without the carry propagation from #1 you got 101b wrongly interpreted due #2 as 1010b ...

  4. You never convert binary to decadic

    Now you should convert base which you do not do anywhere. For integers That is done by dividing the number by printing base (10) and printing the remainders in reverse order. So if your number is not too big convert your result array to single register value (using bitshifts and or) and then convert to decadic string...

    1001b -> 1<<3 | 0<<2 | 0<<1 | 1<<0 = 9 // conversion to single register
    9 / 10 = 0 + remainder 9 -> "9" // division
    

    If the result would be 1010b it would be:

    1001b -> 1<<3 | 0<<2 | 1<<1 | 0<<0 = 10 // conversion to single 
    10 / 10 = 1 + remainder 0 -> "0"  // division
    1  / 10 = 0 + remainder 1 -> "10" // division
    

    If the number is for examle 123:

    123/10 = 12 remainder 3 -> "3"
    12 /10 =  1 remainder 2 -> "23"
    1  /10 =  0 remainder 1 -> "123"
    

    In case your array is big (does not fit into single register) you have to implement bignum division too ...

You are failing in many things at once !!! You should focus on single stuff/task not all bugs together ... I would start with printing some register hardcoded value in binary first (ignore rest of code), then coumulate array to such value, and only then try addition...

Here is my old lib for printing numbers to strings in NASM I wrote decades ago (just digged it out of my archive so you have some inspiration):

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; txtnum: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
txtnum:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;.hex16     num ax >> string hex16 [cs:si], si=end of string adress at zero
;.dec16     num ax >> string dec16 [cs:si], si=end of string adress at zero
;.dec32     num eax >> string dec32 [cs:si], si=end of string adress at zero
;.txt32     num eax << string dec32 [cs:si], si=end of string adress after zero
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.hex16  pusha
    mov cx,4
.hex16l:rol ax,4
    mov bl,al
    and bl,15
    add bl,'0'
    cmp bl,'9'
    jbe .hex16r
    add bl,'A'-'0'-10
.hex16r:mov [cs:si],bl
    inc si
    loop    .hex16l
    mov [cs:si],cl
    popa
    add si,4
    ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.dec16: push    ax
    push    bx
    push    dx
    mov bx,10
    inc si
    cmp ax,10
    jb  .dec16r
    inc si
    cmp ax,100
    jb  .dec16r
    inc si
    cmp ax,1000
    jb  .dec16r
    inc si
    cmp ax,10000
    jb  .dec16r
    inc si
.dec16r:mov [cs:si],bh
    push    si
.dec16l:xor dx,dx
    div bx
    add dl,'0'
    dec si
    mov [cs:si],dl
    cmp ax,0
    jnz .dec16l
    pop si
    pop dx
    pop bx
    pop ax
    ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.dec32: push    eax
    push    ebx
    push    edx
    mov ebx,10
    inc si
    cmp eax,10
    jb  .dec32r
    inc si
    cmp eax,100
    jb  .dec32r
    inc si
    cmp eax,1000
    jb  .dec32r
    inc si
    cmp eax,10000
    jb  .dec32r
    inc si
    cmp eax,100000
    jb  .dec32r
    inc si
    cmp eax,1000000
    jb  .dec32r
    inc si
    cmp eax,10000000
    jb  .dec32r
    inc si
    cmp eax,100000000
    jb  .dec32r
    inc si
    cmp eax,1000000000
    jb  .dec32r
    inc si
.dec32r:mov [cs:si],bh
    push    si
.dec32l:xor edx,edx
    div ebx
    add dl,'0'
    dec si
    mov [cs:si],dl
    cmp eax,0
    jnz .dec32l
    pop si
    pop edx
    pop ebx
    pop eax
    ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.txt32: push    ebx
    push    ecx
    push    edx
    mov eax,0
    mov ebx,10
    mov ecx,0
.txt32l:mov cl,[cs:si]
    inc si
    or  cl,cl
    jz  .txt32e
    cmp cl,'0'
    jb  .txt32e
    cmp cl,'9'
    ja  .txt32e
    sub cl,'0'
    mul ebx
    add eax,ecx
    jmp .txt32l
.txt32e:or  edx,edx
    jz  .txt32x
    mov eax,-1
.txt32x:pop edx
    pop ecx
    pop ebx
    ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; end. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1