Как я могу подсчитать количество отрицательных чисел в массиве в MASM?

Я написал несколько программ на MASM, например, одну, которая может создать треугольник из букв и пробелов в зависимости от числа, которое вы ему задали, и другую, которая может складывать и вычитать и показывать вам, как она делает это с числами, которые вы вводите. дайте это, так что я надеюсь, что это даст вам представление о том, как много я знаю MASM. Мой вопрос заключается в следующем. Мне дали массив, который содержит положительные или отрицательные числа. Моя работа состоит в том, чтобы просмотреть массив и выяснить, что есть что, и вернуть количество отрицательных значений в массиве. Я понимаю, что означает написанный мной код и что означают и делают все отдельные элементы, но я хотел знать, не могли бы вы помочь мне понять, как различать отрицательные и положительные числа, чтобы я мог это реализовать.

;; 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
;;;;;;;;;;;;;;;;;;;;
;;

person Marlin Hankin    schedule 25.04.2013    source источник


Ответы (1)


Есть много способов сделать это. Например (кстати, ни один из них не тестировался, и логика цикла не показана, чтобы сделать ее короткой)

 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

И бесконечные вариации. Выбирайте.

person harold    schedule 25.04.2013
comment
Совершенно уверен. Только в первый раз старший бит eax должен быть равен нулю. Логика позаботится об этом в следующий раз. Просто хотел добавить это для запутывания. - person Aki Suihkonen; 25.04.2013
comment
@AkiSuihkonen, но что случилось с этим 32-битным setcc? Я даже не знала, что у нас такое есть, но было бы здорово - person harold; 25.04.2013
comment
Да, в самом деле. Это портит запутанную часть. Придется сделать это как cmp [array], 0; setn al; add edx, eax; с однократным сбросом eax. Может быть, поэтому setcc так редко встречается. - person Aki Suihkonen; 25.04.2013
comment
@AkiSuihkonen жаль, это был хороший трюк. Я видел 32-битный setcc, предложенный на sirrida, так что, может быть, когда-нибудь... - person harold; 25.04.2013
comment
Я думал, что это будет намного сложнее, но как только я понял, куда вы клоните, я понял это. Я просто ненавижу то, как это не очень прямо с вами, но как только вы получите представление о том, что куда идет и что делает, сборка становится довольно забавной. Я закрываюсь только при мысли о необходимости писать всю программу на ассемблере, лол. - person Marlin Hankin; 26.04.2013