计算 DW 数组中等于 1 的元素个数

Counting number of elements equal to 1 in DW array

我想计算数组中 1 的个数(使用 MASM32)。在第一次迭代中,我在 EAX 中得到了一些奇怪的值。我得到的不是 00000000,而是 00010000。因此在计数器 ECX.

中也得到了不正确的值
.386  
.model small  
.data  
var1 dw 0,1,1 
.code  
main PROC  
   LEA ESI, var1  
   MOV EBX, 3  
   MOV ECX, 0  
L1:CMP EBX, 0  
   JE L3  
   MOV EAX, [ESI]  
   CMP EAX, 0  
   JE L2  
   INC ECX  
L2:DEC EBX  
   ADD ESI, 2  
   JMP L1  
L3:INVOKE ExitProcess, 0  
main ENDP  
END main  

查看此图片,在 EAX 中获取 00010000 而不是 00000000,因为 [ESI] 处的内容在开始时为 0

您将 var1 定义为 word(16 位)而不是 dword,但您正在加载 dword(32 位)因为您加载到 eax 这是一个 32 位大小的寄存器,所以您将获得内存中的下一个字(即 1 ) 在你的双字的上半部分。看这个例子:

x dw 1
y dw 2
z dw 3

# resulting memory layout:
# 01 00 02 00 03 00
# \_x_/ \_y_/ \_z_/


mov ax, [x] # you get 0001
mov eax, [x] # you get 00020001 !! because you are reading x AND y
movzx eax, word ptr [x] # you get 00000001

# 01 00 02 00 03 00
# \_x_/ \_y_/ \_z_/
# \ax_/
# \___eax___/


mov ax, [y] # you get 0002
mov eax, [y] # you get 00030002 !! because you are reading y AND z
movzx eax, word ptr [y] # you get 00000002

# 01 00 02 00 03 00
# \_x_/ \_y_/ \_z_/
#       \ax_/
#       \___eax___/

在您的例子中,它不是另一个命名变量,而是 var1 的第二部分(您有 var1 dw 0,1,1,因此您定义了三个值为 0000、0001、0001 的词 - 但同样适用这里和上面的例子一样)。

var1 dw 0,1,1

# 00 00 01 00 01 00
# \___/ \___/ \___/
#  \var1 \     \var1+4
#         \var1+2
# \ax_/
# \___eax___/

因此,要么使用 dd 而不是 dw 使您的变量成为双字(然后还将 esi 增加 4 而不是 2),或者通过存储来读取一个词它进入一个较小的寄存器,如 ax 或使用 movzx(或 movsx,如果你需要一个带符号的值)和 word ptr,它扩展值以填充整个寄存器。

var1 dd 0,1,1

# 00 00 00 00 01 00 00 00 01 00 00 00
# \__var1___/ \_var1+4__/ \_var1+8__/
# \___eax___/

请注意,如果您决定使用ax,那么请记住,将数据加载到其中不会修改eax的上半部分,它会保留其先前的值,因此您不能写进入 ax 然后从 eax 读取,因为你会再次在上半部分得到意想不到的东西。然后,您还需要执行 cmp ax, 0 而不是 cmp eax, 0。您需要始终清楚自己正在读或写什么(以及多少)。