-3

Please help how to go by binary array (values of array are filled in program) and assign the total variable the value total = total * 2 + digit (digit is binary digit from array) and after the loop finished, output value of variable total in the console and do it in the masm32?

array = [1, 1];
let total = 0;
for (let i = 0; i < length_of_array; i++){
 
total = total * 2 + array[i];
 
}
 
print(total); // 3
Peter Cordes
  • 286,368
  • 41
  • 520
  • 731
  • 1
    As I commented on the [previous version of this question](https://stackoverflow.com/questions/67533107/how-to-convert-binary-array-to-decimal-number-and-output-it-in-the-console-in-ma), the *efficient* ways in x86 asm involve MMX or SSE2 for `pmovmskb` - [How to create a 8 bit mask from lsb of \_\_m64 value?](https://stackoverflow.com/a/52096752). Otherwise you typically want `cmp` / `adc eax,eax` to shift CF into EAX. – Peter Cordes May 16 '21 at 16:56

1 Answers1

0

You could write the following code:

.386
.model flat, stdcall
.stack 1000h

include \masm32\include\masm32rt.inc

.data
array db 1, 1 ; defining the array
arrlength db 2 ; array length

consoleOutHandle dd ? 
bytesWritten dd ? 
message db "------",13,10
lmessage dd 8 ; print declarations

.code
main proc

    mov ebx, offset array ; array location
    mov eax, 0 ; total
    mov ecx, 0 ; i
    loopLabel:
        push ecx
        mov ecx, 2
        mov edx, 0
        mul ecx ; eax = eax * 2
        pop ecx
        add ebx, ecx ; ebx is pointing to array[i]
        add al, byte ptr [ebx]
        sub ebx, ecx ; resetting ebx
        inc ecx
        cmp cl, byte ptr [arrlength] ; checking if i is bigger or equal to the length
    jb loopLabel
    ; the print section
    invoke dwtoa, eax, offset message
    INVOKE GetStdHandle, STD_OUTPUT_HANDLE
    mov consoleOutHandle, eax 
    mov edx,offset message 
    pushad    
    mov eax, offset message
    INVOKE WriteConsoleA, consoleOutHandle, edx, eax, offset bytesWritten, 0
    popad

    invoke ExitProcess, 0
main endp

end main
; 00F9FC60

This works, but depending on which environment you're running it, you might need to change the print section to run in a different manner.

Shufi123
  • 221
  • 3
  • 10
  • 4
    That's correct (I think) but very inefficient and not a good example for future readers. You don't need widening `mul` to multiply by 2, especially not when you don't need the high half. Just `add eax, eax` or `shl eax, 1`. Also, `mov edx, 0` right before `mul` overwrites EDX is pointless. You could use `mov edx, 2` if you really wanted to use `mul edx`, but even `imul eax, 2` would be less bad than `mul`. – Peter Cordes May 16 '21 at 15:05
  • 3
    You also don't need to add/sub the pointer and counter; either use `[ebx + ecx]`, or increment the *pointer* directly. e.g. `inc ebx` / `dec ecx / jnz loopLabel`. (And outside the loop, `movzx ecx, byte ptr [arrlength]` if you want to store the array length in memory at all, instead of `mov ecx, lengthof array`; I think that's the right MASM operator). – Peter Cordes May 16 '21 at 15:08
  • 3
    For this problem specifically, another trick to optimize `total = total*2 + digit` is to get CF set according to digit (e.g. with `cmp zeroed_reg, byte ptr [ebx]`), then `adc eax,eax` to shift in the CF value into the bottom of the register. Or of course SIMD to convert multiple booleans at once is much more efficient if you have MMX or SSE2. – Peter Cordes May 16 '21 at 15:11
  • @Shufi123, it gave error that masm32rt.inc not found, but after I added C:/ the error disappeared and it gave new errors like windows.inc not found I added in the masm32rt.inc C:/ to the path and it gave the similar errors and after I added again C:/ to the pathes it gave now warnings like: LINK : warning L4051: \masm32\lib\masm32.lib : cannot find library LINK : warning L4051: \masm32\lib\gdi32.lib : cannot find library What do I need to do to fix this all? – Fedor Pasynkov May 16 '21 at 17:34
  • and even if you want to set a register to zero then [use `xor reg, reg` instead of `mov reg, 0`](https://stackoverflow.com/q/33666617/995714) – phuclv May 17 '21 at 01:18
  • On the topic of non-SIMD options: Could pack 4 bytes at a time with a single multiplication (https://stackoverflow.com/questions/14547087/extracting-bits-with-a-single-multiplication). For example, multiply by 0x10204080 (get 4 bits packed on the right/msb side) and then shift right by 28. – stepan May 17 '21 at 07:54
  • @FedorPasynkov Then you must have a different MASM environment. For the others complaining, I know that you could shift left and multiply by 2, but if something needs to be changed in the code, it would be easier to use my code (eg switching it from multiplying by 2 to multiplying by 3). Also, pointing to [ebx + ecx] won't work on all compilers. – Shufi123 May 17 '21 at 10:05