Search code examples
assemblymasm

How can I count the amount of negative numbers in an arrary in MASM?


I have written a few programs in MASM such as one that is able to produce a triangle out of letters and spaces depending on the number you give it and one that is able to add and subtract and show you as it is doing it with numbers you give it so I hope this gives you an idea about how much MASM I know. My question is this. I have been given an array that contains numbers of either positive or neg. My job is to go through the array and figure out which is which and return the number of negatives in the array. I understand what the code I put means and what all the individual elements mean and do but I wanted to know if you all could help me in trying to figure out how to distinguish between the neg and positive numbers so I can implement it.

;; Do not modify this block of code 
;; (until where comment says you can start your code)
;;
    call Clrscr
    call Randomize       ; Initialize random number generator

;;;;; Generate NUM_NUMS random numbers and store them into the nums array

    mov ecx,NUM_NUMS     ; Number of times to loop
    mov esi,0            ; Relative offset for nums array

NUM_LOOP:
    call Random32        ; Generate a random number
    mov [nums+esi], eax  ; Move random number into array

    add esi,TYPE nums    ; move esi to relative offset of next array element
    LOOP NUM_LOOP        ; end of loop

;;
;; End of do not modify block
;;;;;;;;;;;;;;;;;;;;
;;

Solution

  • There are many ways to do that. For example (none of these are tested, by the way, and loop logic not shown to keep it short)

     1:
      cmp [nums+esi], 0 ; compare with 0
      jnl _skip
      inc edx           ; increment count if < 0
    _skip:
     2:
      mov eax, [nums+esi]
      test eax, eax     ; update sign flag with sign bit
      jns _skip
      inc edx           ; increment count if sign was set (ie, < 0)
    _skip:
     3:
      mov eax, [nums+esi]
      add eax, eax      ; create unsigned overflow if < 0
      jnc _skip
      inc edx           ; increment count if overflowed (ie, < 0)
    _skip:
     4:
      mov eax, [nums+esi]
      shl eax, 1        ; same as 3, but an other way to create overflow
      jnc _skip
      inc edx
    _skip:
     5:
      mov eax, [nums+esi]
      add eax, eax
      adc edx, 0        ; add the overflow directly to the count
     6:
      mov eax, [nums+esi]
      shl eax, 1
      adc edx, 0        ; same as 5
    _skip:
     7:
      mov eax, [nums+esi]
      sar eax, 31       ; create 0 if non-negative, -1 if negative
      sub edx, eax      ; subtract -1 from count if negative
     8:
      mov eax, [nums+esi]
      shr eax, 31       ; create 0 if non-negative, 1 if negative
      add edx, eax      ; add 1 to count if negative
     9:
      movdqa xmm0, [nums + esi]
      psrad xmm0, 31
      psubd xmm1, xmm0   ; same idea as 7, but with 4 in parallel
     10:
      movdqa xmm0, [nums + esi]
      psrld xmm0, 31
      paddd xmm1, xmm0   ; same idea as 8, but with 4 in parallel
     11:
      cmp [nums+esi], 0
      lea eax, [edx + 1] ; create count+1
      cmovl edx, eax     ; update count with incremented count if < 0
     12:
      xor eax, eax
      cmp [nums+esi], eax
      setl al            ; 0 if non-negative, 1 if negative
      add edx, eax
     13:
      cmp [nums+esi], 0
      setl al
      movzx eax, al    ; same idea as 12, but no recombination penalty
      add edx, eax
    

    And endless variations. Take your pick.