Search code examples
exceptionassemblyx86masmmasm32

Using a pointer arg to my function throws an exception


I am currently getting an "exception thrown" error on the line

mov      [ebx], eax

I can't find a solution because all of them use this exact same code and it works for them.

This is an exact copy from my lecture notes and it seems to work for other people except for me.


 TITLE Program Template     (template.asm)

; Author:
; Last Modified:
; OSU email address: 
; Course number/section:
; Project Number:                 Due Date:
; Description:

INCLUDE Irvine32.inc

.data
intro           BYTE    "Fun with Arrays! by ", 0
instruction BYTE    "This program generates random numbers in the range [100 .. 999], displays the original list, sorts the list, and calculates the median value. Finally, it displays the list sorted in descending order.", 0


request         DWORD   ?
ask_user        BYTE    "How many numbers should be generated? [10 ... 200]: ", 0

.code
main PROC

    ;call   randomize
    call    introduction

    push    OFFSET request
    call    getData

    exit    ; exit to operating system
main ENDP

introduction PROC
     mov    edx, OFFSET intro
     call   WriteString
     call   CrLf
     mov    edx, OFFSET instruction
     call   WriteString
     call   CrLf
introduction ENDP

getData PROC
    push    ebp
    mov     ebp, esp

    mov     edx, OFFSET ask_user
    call    WriteString
    call    ReadInt
    mov     ebx, [ebp+8]
    mov     [ebx], eax
    pop     ebp
    ret     4
getData ENDP

END main

Solution

  • introduction is missing a ret

    Execution falls through from the last instruction of introduction to the first instruction of getData. Execution of machine-code always continues to the next address in memory after the current instruction (unless you use a call/ret/branch); labels and proc declarations are just markers. (Why is no value returned if a function does not explicity use 'ret')

    This happens without a valid pointer on the stack. (Because main calls introduction first, without first pushing an address.)


    You can look for bugs like this in a debugger by single-stepping your code; the fall-through instead of return to main should catch your attention!

    Or use your debugger's backtrace function to see where the call came from: you'll see you reached this line in getData from call introduction, not from call getData.


    I'd recommend using a call-clobbered (aka volatile) register for the temporary inside getData. (EAX, ECX, or EDX). ebx is normally call-preserved, so main, and main's caller, expects their EBX value to still be there when the functions return. (But your main doesn't return or use EBX, so there's no actual bug, just a custom calling convention.)