Search code examples
assemblymasmirvine32

MASM: Access Violation Writing Location


using MASM 8086
program determines the largest value in the given arrays

Unhandled exception gets thrown when esi is increased. This does not appear to happen when largestVal is defined as a DWORD. However, this prevents .IF largestVal < ebx from working.

Include Irvine32.inc

FindLargest PROTO, pArr: PTR DWORD, Count: DWORD

.data

str1 BYTE "arr1: ", 0
str2 BYTE "arr2: ", 0
str3 BYTE "arr3: ", 0

arr1 SDWORD +1122h, +2233h, -3344h
arr2 SDWORD +2233h, +3344h, +4455h, +6677h

.code

main PROC
call Clrscr

INVOKE FindLargest, ADDR arr1, LENGTHOF arr1
mov edx, OFFSET str1
call WriteString    
call WriteInt       


INVOKE FindLargest, ADDR arr2, LENGTHOF arr2
mov edx, OFFSET str2
call WriteString
call WriteInt

exit
main ENDP

FindLargest PROC USES ebx ecx esi, pArr: PTR DWORD, Count: DWORD
LOCAL largestVal: SDWORD

mov esi, pArr       
mov ecx, Count
mov largestVal, -2147483648

L1:

mov ebx, [esi]

.IF largestVal < ebx

mov largestVal, ebx

.ENDIF

add esi, 4                 ; Where exception gets thrown                
loop L1

mov eax, largestVal         
ret
FindLargest ENDP
END main

Solution

  • It's a feature of VS2015. The code works fine with VS2013

    Visual Studio 2015 stumbles over this line:

    .IF largestVal < ebx
    

    and produces total crap, amongst others the address ebp-7D for largestVal that is beyound the stack frame. Correct is ebp-4.

    I've figured out two workarounds.

    1) Decouple largestVal from the .IF directive:

    ...
    mov eax, largestVal
    .IF eax < ebx
    mov largestVal, ebx
    .ENDIF
    ...
    

    2) Don't use the MASM preprocessor, use pure assembly instructions instead:

    ...
    cmp largestVal, ebx
    jge @F                  ; Jump forward to the next @@
    mov largestVal, ebx
    @@:
    ...