I want to count the number of 1's in an array (using MASM32). In the first iteration I am getting some weird value in EAX
. Instead of 00000000, I'm getting 00010000. Hence also getting an incorrect value in the counter 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
See this image, getting 00010000 in EAX
instead of 00000000 as content at [ESI]
is 0 at begining
CodePudding user response:
You defined var1
as word (16-bit) and not dword, but you are loading a dword (32-bit) because you load into eax
which is a 32-bit-sized register, so you are getting the next word in memory (which is 1
) in the upper half of your dword. See this example:
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___/
In your case, it's not another named variable but the second part of var1
(you have var1 dw 0,1,1
so you define three words with values 0000, 0001, 0001 - but the same thing applies here as with the example above).
var1 dw 0,1,1
# 00 00 01 00 01 00
# \___/ \___/ \___/
# \var1 \ \var1 4
# \var1 2
# \ax_/
# \___eax___/
So, either make your variable a dword using dd
instead of dw
(and then also increase esi
by 4 instead of 2), or read a word by either storing it into a smaller register like ax
or using movzx
(or movsx
if you need a signed value) with word ptr
, which extends the value to fill the whole register.
var1 dd 0,1,1
# 00 00 00 00 01 00 00 00 01 00 00 00
# \__var1___/ \_var1 4__/ \_var1 8__/
# \___eax___/
Note that if you decide to use ax
, then remember that loading data into it won't modify the upper half of eax
, it will keep its previous value, so you cannot write into ax
and then read from eax
, because you will again get unexpected things in the upper half. You'd then need to do cmp ax, 0
instead of cmp eax, 0
too. You need to be always aware of what exactly (and how much) you are reading or writing.