Assembly 如何在MASM中计算数组中负数的数量?

Assembly 如何在MASM中计算数组中负数的数量?,assembly,masm,Assembly,Masm,我已经用MASM写了一些程序,比如一个可以根据你给出的数字,用字母和空格生成一个三角形的程序,一个可以用你给出的数字进行加减和显示的程序,所以我希望这能让你知道我知道多少MASM。 我的问题是。我得到了一个数组,其中包含正数或负数。我的工作是遍历数组,找出哪个是哪个,然后返回数组中负片的数量。我理解我写的代码的意思,以及所有元素的含义和作用,但我想知道你们是否能帮助我找出如何区分负数和正数,以便我能够实现它 ;; Do not modify this block of code ;; (unt

我已经用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
;;;;;;;;;;;;;;;;;;;;
;;

有很多方法可以做到这一点。例如(顺便说一句,这些都没有经过测试,并且没有显示循环逻辑以保持简短)

1:
cmp[nums+esi],0;与0相比
跳转
公司edx;如果小于0,则递增计数
_跳过:
2:
mov eax,[nums+esi]
测试eax,eax;用符号位更新符号标志
jns\u跳过
公司edx;设置符号时的增量计数(即,<0)
_跳过:
三:
mov eax,[nums+esi]
添加eax,eax;如果<0,则创建无符号溢出
跳转
公司edx;溢出时的增量计数(即<0)
_跳过:
4:
mov eax,[nums+esi]
shl-eax,1;与3相同,但另一种创建溢出的方法
跳转
公司edx
_跳过:
5:
mov eax,[nums+esi]
添加eax,eax
adc-edx,0;将溢出直接添加到计数中
6:
mov eax,[nums+esi]
shl eax,1
adc-edx,0;与5相同
_跳过:
7:
mov eax,[nums+esi]
sar-eax,31;如果为非负,则创建0;如果为负,则创建1
次级edx、eax;如果为负,则从计数中减去-1
8:
mov eax,[nums+esi]
shr-eax,31;如果为非负,则创建0;如果为负,则创建1
添加edx、eax;如果为负,则加1计数
9:
movdqa xmm0,[nums+esi]
psrad xmm0,31
psubd xmm1,xmm0;与7的想法相同,但与4平行
10:
movdqa xmm0,[nums+esi]
psrld xmm0,31
paddxmm1,xmm0;与8相同,但与4平行
11:
cmp[nums+esi],0
lea-eax[edx+1];创建计数+1
cmovl edx,eax;如果小于0,则使用递增的计数更新计数
12:
异或eax,eax
cmp[nums+esi],eax
setl al;如果为非负,则为0;如果为负,则为1
添加edx、eax
13:
cmp[nums+esi],0
塞特尔
movzx-eax,al;与12相同,但没有重组惩罚
添加edx、eax

还有无尽的变化。你自己选吧。

有很多方法可以做到这一点。例如(顺便说一句,这些都没有经过测试,并且没有显示循环逻辑以保持简短)

1:
cmp[nums+esi],0;与0相比
跳转
公司edx;如果小于0,则递增计数
_跳过:
2:
mov eax,[nums+esi]
测试eax,eax;用符号位更新符号标志
jns\u跳过
公司edx;设置符号时的增量计数(即,<0)
_跳过:
三:
mov eax,[nums+esi]
添加eax,eax;如果<0,则创建无符号溢出
跳转
公司edx;溢出时的增量计数(即<0)
_跳过:
4:
mov eax,[nums+esi]
shl-eax,1;与3相同,但另一种创建溢出的方法
跳转
公司edx
_跳过:
5:
mov eax,[nums+esi]
添加eax,eax
adc-edx,0;将溢出直接添加到计数中
6:
mov eax,[nums+esi]
shl eax,1
adc-edx,0;与5相同
_跳过:
7:
mov eax,[nums+esi]
sar-eax,31;如果为非负,则创建0;如果为负,则创建1
次级edx、eax;如果为负,则从计数中减去-1
8:
mov eax,[nums+esi]
shr-eax,31;如果为非负,则创建0;如果为负,则创建1
添加edx、eax;如果为负,则加1计数
9:
movdqa xmm0,[nums+esi]
psrad xmm0,31
psubd xmm1,xmm0;与7的想法相同,但与4平行
10:
movdqa xmm0,[nums+esi]
psrld xmm0,31
paddxmm1,xmm0;与8相同,但与4平行
11:
cmp[nums+esi],0
lea-eax[edx+1];创建计数+1
cmovl edx,eax;如果小于0,则使用递增的计数更新计数
12:
异或eax,eax
cmp[nums+esi],eax
setl al;如果为非负,则为0;如果为负,则为1
添加edx、eax
13:
cmp[nums+esi],0
塞特尔
movzx-eax,al;与12相同,但没有重组惩罚
添加edx、eax

还有无尽的变化。你挑吧。

非常肯定。只有eax的msb第一次必须为零。下一次逻辑会解决这个问题。我只是想添加它来混淆。@AkiSuihkonen但是32位的
setcc
是怎么回事?我甚至不知道我们有这个,但那将是相当令人敬畏的。它破坏了混淆部分。必须按
cmp[array]的方式执行,0;setn等人;添加edx、eax且eax清除一次。也许这就是为什么setcc如此罕见的原因。@Akisuikonen遗憾的是,这是一个很好的把戏。我在sirrida上看到一个32位的
setcc
,所以也许有一天..我认为这会比那困难得多,但一旦我明白了你的意思,我就明白了。我只是讨厌它对你不是很直接,但一旦你知道什么去哪里,什么做什么,组装是相当有趣的。一想到要用汇编语言写一个完整的程序,我就笑了。非常肯定。只有eax的msb第一次必须为零。下一次逻辑会解决这个问题。我只是想添加它来混淆。@AkiSuihkonen但是32位的
setcc
是怎么回事?我甚至不知道我们有这个,但那将是相当令人敬畏的。它破坏了混淆部分。必须按
cmp[array]的方式执行,0;setn等人;添加edx、eax且eax清除一次。也许这就是为什么setcc如此罕见的原因。@Akisuikonen遗憾的是,这是一个很好的把戏。我在sirrida上看到了一个32位的
setcc
,所以也许有一天..我认为这会比那困难得多,但一旦我赶上了drif
 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