-4
; Author:
; Date:
; This is the Visual Studio 2012 version

; Preprocessor directives
.586        ; use the 80586 set of instructions
.MODEL FLAT ; use the flat memory model (only 32 bit addresses, no segment:offset)

; External source files
INCLUDE io.h   ; header file for input/output
INCLUDE fio.h  ; header file for floating point conversions to and from ASCII

; Stack configuration
.STACK 4096    ; allocate 4096 bytes for the stack

; Named memory allocation and initialization
; Use REAL4 for floating point values
.DATA
    prompt1     BYTE    "Enter circumference: ", 0 ; Basic prompt
    string      BYTE    40 DUP (?)
    BoxLabel1   BYTE    "The radius is "
    radius      BYTE    12 DUP (?), 0

    msg1        BYTE    "The circle circumference is: ", 0ah
    circumf2    BYTE    12 DUP (?), 0ah
    msg2        BYTE    "The circle area is: ", 0ah
    area2       BYTE    12 DUP (?), 0

radiusInput REAL4   1.0
pi          REAL4   3.14
two         REAL4   2.0
areA        REAL4   1.0
circumf     REAL4   1.0

; procedure definitions
.CODE
_MainProc PROC
;************ INPUT *************
    input   prompt1, string, 40         ; read ASCII characters
    atof    radiusInput, string         ; Convert (ASCII TO FLOAT) macro
;********************************   
    finit   
    push    radiusInput
    call    findCircumf ; BREAKS HERE!!!!


;   call    findArea

;done:

;************ OUTPUT ************
    ftoa    radius, radiusInput
    ftoa    area2, areA
    ftoa    circumf2, circumf
    output  BoxLabel1, msg1
;********************************

;*********** CLEAN-UP ***********
    mov     EAX, 0  ; exit with return code 0
    ret
;********************************
_MainProc ENDP

;##################### findCircumf PROCEDURE ##################
findCircumf PROC
; ******** CIRCUMFERENCE ********
; Formula 2*Pi*R
    fld     two             ; ST(0) has 2.0
    fld     pi              ; ST(0) has 3.14 ST(1) 2.0
    fmul    st(0), st(1)    ; ST(0) has 6.28    2*Pi
    fld     radiusInput     ; ST(0) has radius input (3.5) ST(1) has 6.28
    fmul    ST(0), ST(1)    ; ST(0) has 21.98   2*Pi*R
    fst     circumf
;********************************
findCircumf ENDP

;###################### findArea PROCEDURE #####################
findArea PROC
;************ AREA **************
; Forumla R*R*Pi
    fld     radiusInput     ; ST(0) has radius input (3.5) 
    fmul    st(0), st(0)    ; ST(0) has 12.25   R*R (or R^2)
    fld     pi              ; ST(0) has 3.14    ST(1) has 12.25
    fmul    st(0), st(1)    ; ST(0) has 38.465  R*R*Pi
    fstp    areA            ; areA has 38.465 
;********************************
findArea ENDP
END   ; end of source code

Breaks at call findCircumf with error list saying

windows32.exe has triggered a breakpoint.
The thread 0x1570 has exited with code 0 (0x0).
The program '[628] windows32.exe' has exited with code 0 (0x0).

I know I did something wrong. I am assuming it has to do with my return. In the procedure the reurn value is in ST(0). I am not sure what I did wrong, I am using floating points.

GeekyDewd
  • 321
  • 1
  • 2
  • 18
  • 1
    First of all there is no return statements at the end of the procedure(s). – GeekyDewd May 06 '16 at 00:31
  • 1
    If MASM doesn't insert a `ret` for you, then that's one problem. Besides that, your functions return with the x87 stack not empty. Michael Petch and I wrote some intro-to-x87 answers over [on another question](http://stackoverflow.com/q/36923943/224132). Besides that, there's an `fldpi` instruction, which uses an internal 66bit-precision constant. You should only load `pi` from memory if you're going to define it to a full correctly-rounded 80bit constant and use `fld tword [pi]`. There's also an `fld1` instruction to load 1.0. – Peter Cordes May 06 '16 at 02:38
  • 1
    Anyway, it sounds like you should run your code in a debugger, and see where it stops. The fact that it crashed somewhere tells you very little. See the [FAQ section of the x86 tag wiki](http://stackoverflow.com/tags/x86/info). Downvoted for not even taking the time to use a debugger and find out where the code crashes or whatever its doing. – Peter Cordes May 06 '16 at 02:39
  • Wait a minute, you were the one that asked that other question I linked, which had problems with not popping as much as you pushed on the x87 stack. Are multiple people using your account? Why did you leave a comment on your own question? – Peter Cordes May 06 '16 at 03:04
  • I assumed you meant it faults somewhere inside `findCircumf`, because the `call` instruction itself won't crash unless there's some kind of linker problem (e.g. jumping to somewhere other than where it should, or to memory that doesn't have execute permission), or if `esp` is pointing somewhere bogus. (It does have to push the return address). You didn't specify what exception the instruction produces, just some eventual Windows error message. – Peter Cordes May 07 '16 at 01:04
  • 1
    Based on your answer, it appears that the `call` instruction itself wasn't what was faulting. So like I said, you didn't show which instruction was actually faulting, just some point before it happened. – Peter Cordes May 07 '16 at 01:07

1 Answers1

-1

1.) First of all there is no return statements at the end of the procedure(s).

2.) Since I am using floating point AND STACK I put finit before each procedure call.

3.) I needed to establish a stack frame in the beginning of each procedure

push    ebp             ; save base pointer
mov     ebp, esp        ; establish stack frame
push    ebx             ; save EBX

4.) Pop the registers from the stack frame before the return on each procedure

pop     ebx             ; restore EBX
pop     ebp             ; restore EBP
ret                     ; return  

Those things fixed my problem.

ChrisF
  • 134,786
  • 31
  • 255
  • 325
GeekyDewd
  • 321
  • 1
  • 2
  • 18
  • 1
    You don't need `finit` if you clean up the x87 stack before returning. (Use `fmulp` instead of `fmul` after two `fld`s, for example.) Returning with extra stuff on the x87 stack will potentially lead to crashes elsewhere in the code. `finit` can be used as a workaround in this case, because your program is simple. – Peter Cordes May 07 '16 at 01:09
  • 1
    Anyway, glad you were able to track down and fix the problem with missing a `ret`. – Peter Cordes May 07 '16 at 01:13