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

标签 assembly x86 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  

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

See this image getting 00010000 in EAX instead of 0000000 as ESI content is 0 at begining

最佳答案

您将 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。您需要始终清楚自己正在读或写的内容(以及多少)。

关于assembly - 计算 DW 数组中等于 1 的元素个数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69390039/

相关文章:

c++ - 我需要帮助开发多态引擎 - 指令依赖树

c - 不清楚的c代码: double underscore in c macro

assembly - JMP 对堆栈和帧指针执行什么操作?

c - x86 汇编中的序言和推送被调用者保存寄存器

assembly - MASM 字符串指令 - 在实模式下段寄存器覆盖前面的 LEA?

assembly - 在 16 位 Turbo Pascal 中访问高性能计数器

linux - 在 Linux 中轻松检查 Intel 汇编操作码

assembly - 此调用(汇编)后的以下指令是什么

assembly - MOV src,dest(或)MOV dest,src?

assembly - 从使用x87 FPU的64位汇编函数返回 float