4

I have created the following program to read in 5 numbers, and then dumpreg to see what numbers were entered...

        INCLUDE Irvine32.inc

    .data
    count = 5
    scores WORD count DUP(? )
    prompt BYTE "Please type an integer score: ", 0

    .code
    GetScores PROTO, wArray:PTR WORD, arraySize : WORD

    main proc


    INVOKE GetScores,OFFSET scores, count

    mov esi, OFFSET scores
    mov ecx, count
    mov ebx, 2
    call DumpMem
    mov eax, 50000
    call Delay

    exit
    main endp

    GetScores PROC, wArray:PTR WORD, arraySize : WORD
    push ebp
    mov ebp, esp
    pushad

    mov esi, wArray
    movzx ecx, arraySize
    cmp ecx, 0; ECX < 0 ?
    jle L2; yes: skip over loop
    L1 :
call ReadInt
mov[esi], eax
add esi, TYPE WORD
loop L1

L2 : popad
    pop ebp
    ret 8
    GetScores ENDP

    END main

This is my first time using stack parameters, and I'm receiving the error Exception thrown at 0x0040365A in Project.exe: 0xC0000005: Access violation writing location 0x0040361C. after entering the first number.

I believe this is due to a problem with my indexing in my array, but am not sure where the issue is. Any and all help is much appreciated!

rkhb
  • 14,159
  • 7
  • 32
  • 60
Bob
  • 1,344
  • 3
  • 29
  • 63
  • 1
    Since the `loop` instruction uses `ecx` you should make sure whole of `ecx` is set not just `cx`. If you insist on using `WORD` argument, use `movzx ecx, arraySize` (adjust syntax as necessary for masm). Also, you read 32 bit `DWORD`s but your array is again of `WORD` type. Change `mov [esi], eax` to `mov [esi], ax` if you insist on that. PS: learn to use a debugger so you can step through your own code. Yes, that should be among the first things to learn. – Jester Dec 10 '15 at 01:29
  • @Jester I have made the changes you have suggested, but am still getting the same error, I've updated my code in my post. Also, you are completely right and I am very good with the debugger on eclipse, but I don't understand enough about assembly to know what I'm seeing while stepping through – Bob Dec 10 '15 at 01:45
  • Where is ReadInt defined? I don't seem to see that code and it seems a likely suspect for a source of your troubles. In particular, is ReadInt modifying ESI in any way? – David Hoelzer Dec 10 '15 at 02:49
  • @DavidHoelzer `ReadInt` is part of the Irvine library, I'm currently lookin for exactly what it does, but It shouldn't be modifying `esi` in any way – Bob Dec 10 '15 at 03:32
  • The Irvine library is documented [here](http://programming.msjc.edu/asm/help) including [readInt](http://programming.msjc.edu/asm/help/source/irvinelib/readint.htm) . It only destroys the _EAX_ register with the return value. – Michael Petch Dec 10 '15 at 07:54

1 Answers1

5

When you use a PROC with parameters (..., wArray:PTR WORD, arraySize : WORD) MASM automatically inserts a prolog and an epilog and calculates the addresses of the parameters according to that prolog.

When you added a second prolog:

push ebp
mov ebp, esp

EBP will be changed and the calculation base for the parameters will be destroyed. Especially ECX gets a ridiculous high value.

Remove your prolog and epilog:

GetScores PROC STDCALL, wArray:PTR WORD, arraySize : WORD
;    push ebp               ; superfluous and harmful prolog
;    mov ebp, esp
    pushad

    mov esi, wArray
    movzx ecx, arraySize
    cmp ecx, 0              ; ECX < 0 ?
    jle L2                  ; yes: skip over loop

    L1 :
    call ReadInt
    mov[esi], eax
    add esi, TYPE WORD
    loop L1

    L2 :
    popad
;    pop ebp                ; superfluous epilog
    ret                     ; becomes `ret 8` due to "STDCALL" in the PROC header
GetScores ENDP
rkhb
  • 14,159
  • 7
  • 32
  • 60
  • Yeah. I always keep saying, only use such features when you fully understand what code the assembler will generate for you. – Jester Dec 10 '15 at 11:31