Question

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.

Was it helpful?

Solution

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top