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

GoA*_*hay 2 x86 assembly masm masm32

我想计算数组中 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  
Run Code Online (Sandbox Code Playgroud)

看这个图片,得到 00010000EAX而不是 00000000 因为内容在[ESI] 开始时是 0

看到此图像在 EAX 中获取 00010000 而不是 0000000,因为 ESI 内容在开始时为 0

Che*_*yDT 6

您定义var1word(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___/
Run Code Online (Sandbox Code Playgroud)

在您的情况下,它不是另一个命名变量,而是第二部分var1var1 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___/
Run Code Online (Sandbox Code Playgroud)

因此,要么使用而不是使变量dd成为双字dw(然后增加esi4 而不是 2),或者通过将其存储到较小的寄存器中来读取单词,例如ax或使用movzx(或者movsx如果您需要有符号值)with 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___/
Run Code Online (Sandbox Code Playgroud)

请注意,如果您决定使用ax,请记住,将数据加载到其中不会修改 的上半部分eax,它将保留其先前的值,因此您无法写入ax然后从中读取eax,因为您将再次在 中得到意想不到的东西上半部分。然后你需要做cmp ax, 0而不是cmp eax, 0太。您需要始终了解您正在阅读或编写的内容(以及数量)。