Search code examples
assemblymasmirvine32

Writing a "simple calculator for 32-bit integers" in MASM using the Irvine32 library. How can I fix this "write access violation" error?


Here is the assignment: Here is the assignment

Here is the link to the documentation for the Irvine32 library (which I must use): http://programming.msjc.edu/asm/help/

Right now I'm just experimenting with how to make a successful template prompt/output, and i'm starting with the addition operation. My issue is that I get a "write access violation" when trying to use WriteString (an Irvine32 procedure) to print the first line of response output. It does print the text on the console, but the error comes up immediately after. What confuses me is that earlier in the program I successfully use WriteString for other strings; it's weird that it doesn't work here.

Here is a screenshot of the error displayed during debugging:

enter image description here

Here is my code:

.386
.MODEL flat,stdcall
.STACK 4096
ExitProcess PROTO,dwExitCode:DWORD
WriteString PROTO
ReadDec PROTO

.DATA

promptLineOne DB "1.  X + Y                    6.  X and Y",13,10,0
promptLineTwo DB "2.  X - Y                    7.  X or Y",13,10,0
promptLineThree DB "3.  X * Y                    8.  not X",13,10,0
promptLineFour DB "4.  X / Y                    9.  X xor Y",13,10,0
promptLineFive DB "5.  X mod Y                    10.  Exit Program",13,10,0
adding DB "Adding X and Y; enter X, then enter Y",0
added DB "The sum of X and Y is: ",0
tryAgain DB "Try again",0

.CODE

prompt PROC
  MOV ECX,5
  MOV EAX,0
  MOV EDI,OFFSET promptLineOne
  L1:
    MOV EDX,EDI
    INVOKE WriteString
    L2:
        INC EDI
        MOV AL,[EDI]
        CMP EAX,0
        JNZ L2
        INC EDI
    LOOP L1

RET
prompt ENDP

calculate PROC
  MOV EDX,OFFSET adding
  INVOKE WriteString
  op1 DD ?
  op2 DD ?
  result DD ?
  L1:
    INVOKE ReadDec
    JNC chastise
    JC FirstPass
    JNC L1
  FirstPass:
    MOV op1,EAX
  L2:
    INVOKE ReadDec
    JNC chastise
    JC SecondPass
    JNC L2
  SecondPass:
    MOV op2,EAX
    ADD EAX,op1
    ADD EAX,op2
    MOV result,EAX

    MOV EDX,OFFSET added
    INVOKE WriteString
    MOV EDX,OFFSET result
    INVOKE WriteString
RET
calculate ENDP

chastise PROC
  MOV EDX,OFFSET tryAgain
  INVOKE WriteString
RET
chastise ENDP

main PROC
  INVOKE prompt
  INVOKE ReadDec
  INVOKE calculate

  INVOKE ExitProcess,0
main ENDP

END main

Thanks for taking a look! :)


Solution

  • Unlike c++, asm doesn't allow you to define variables at any point in your code. Like this:

    calculate PROC
      MOV EDX,OFFSET adding
      INVOKE WriteString
      op1 DD ?
      op2 DD ?
      result DD ?
      L1:
        INVOKE ReadDec
        JNC chastise
    

    This will do the mov, do the invoke, then attempt to execute whatever instruction lives at op1. Since the ? means the contents of this location are undefined, who knows what it contains? For sure it isn't going to do what you intend.

    It's easy to get used to high level languages where the compiler knows the difference between data and code. But in asm, if you put it in your .code section, it's code.