INCLUDE Irvine32.inc
.data
testArray BYTE 1,2,3,4,5
array BYTE 5,4,3,2,1
; Definition
validateArray PROTO byteArray:PTR BYTE
.code
main PROC
INVOKE validateArray, ADDR byteArray
main ENDP
validateArray PROC byteArray:PTR BYTE
mov esi, byteArray ; should point to array, but does not
mov edi, 0
call DumpRegs
L1: mov eax, byteArray[edi * 1] ; not 5, the first element in the array as expected
call WriteDec
inc edi
call CrLf
Loop L5
validateArray ENDP
I am required to use a BYTE array here and the problem I am seeing is I am not able to get to each element in the array correctly. This all should point to the array and increment through the 1-byte integers, but it is not even at the first element and then jumping around unexpectedly when I was debugging and viewing the memory addresses. I am wondering if I am missing something obvious. I have tried for days to get the procedure to step through each element. The goal was to compare against the testArray, but I am unable to step through the array using a procedure. I have been able to do all this without a procedure and trying to implement this now with procedures.
There are a lot of issues. The program doesn't even assemble. At least it lacks of ret
at the end of the procedure validateArray
, an ExitProcess
at the end of main
and an END main
at the end of the program. I guess INVOKE validateArray, ADDR byteArray
and Loop L5
are typos.
1) INVOKE validateArray, ADDR byteArray
is obviously a typo. I guess you meant testArray
and will call it this way below.
2) byteArray
is a stack address. byteArray[edi]
adds EDI
to this address (*1
is superfluous). mov eax, byteArray[edi ]
loads 4 bytes from the stack. It will contain the pointer to byteArray
if EDI
=0 and else crap. You have first to load the value of byteArray
to get the pointer to testArray
. Then you can dereference it with brackets:
mov esi, byteArray ; ESI: pointer to the first byte of testArray
mov eax, [esi] ; EAX: dword value at [ESI]
add esi, 1 ; Pointer to the next byte of testArray
3) mov eax, byteArray[edi * 1]
loads 4 bytes (32 bits) into EAX
regardless of the denoted type. After the first call (corrected to the right pointer) e.g. EAX
holds the values of the first four elements of testArray
: 1,2,3,4, got them little endian: EAX
=0x04030201. WriteDec
will output the decimal value "67305985". Since you need EAX
for WriteDec use the special x86-instruction for loading a byte into a dword-register:
movzx eax, byte ptr [esi]
The size specifer BYTE PTR
informs the assembler that it shall expand a byte to EAX
. MASM can't know that since it's also possible to expand a word.
If you want to expand a signed byte to a signed dword (eventually negative):
movsx eax, byte ptr [esi]
BTW: You don't need a PROTO-Declaration if your INVOKE is referring "upwards", i.e. the validateArray-PROC is defined before it is called.
I corrected your code a little bit to get a working program:
INCLUDE Irvine32.inc
.data
testArray BYTE 1,2,3,4,5
.code
validateArray PROC byteArray:PTR BYTE
mov esi, byteArray
mov ecx, SIZEOF testArray ; ecx is needed for loop!
_Loop:
movzx eax, byte ptr [esi] ; movzx: load one unsigned byte in a 32-bit-register
call WriteDec
call CrLf
add esi, 1
loop _Loop
ret
validateArray ENDP
main PROC
INVOKE validateArray, ADDR testArray
INVOKE ExitProcess, 0
main ENDP
END main