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