【问题标题】:Procedures with floating points breaking浮点数中断的程序
【发布时间】:2016-08-31 22:01:28
【问题描述】:
; 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

在调用 findCircumf 时中断并显示错误列表

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).

我知道我做错了什么。我假设这与我的回归有关。 在该过程中,reurn 值在 ST(0) 中。我不确定我做错了什么,我使用的是浮点数。

【问题讨论】:

  • 首先,程序结束时没有返回语句。
  • 如果 MASM 没有为您插入 ret,那么这是一个问题。除此之外,您的函数返回时 x87 堆栈不为空。 Michael Petch 和我在 on another question 上写了一些介绍性的 x87 答案。除此之外,还有一条fldpi 指令,它使用内部66 位精度常量。如果要将pi 定义为完全正确舍入的80 位常量并使用fld tword [pi],则应仅从内存中加载pi。还有一个 fld1 指令来加载 1.0。
  • 无论如何,听起来你应该在调试器中运行你的代码,看看它在哪里停止。它在某处坠毁的事实告诉你很少。请参阅FAQ section of the x86 tag wiki。由于甚至没有花时间使用调试器并找出代码崩溃的位置或它在做什么而被否决。
  • 等一下,你是问我链接的另一个问题的人,这个问题没有像你在 x87 堆栈上推送的那样弹出那么多问题。是否有多人使用您的帐户?您为什么对自己的问题发表评论?
  • 根据您的回答,call 指令本身似乎不是问题所在。所以就像我说的,你没有显示哪条指令实际上是错误的,只是在它发生之前的某个时间点。

标签: function assembly stack


【解决方案1】:

1.) 首先,过程结束时没有返回语句。

2.) 因为我使用浮点和堆栈,所以我在每个过程调用之前都放了 finit。

3.) 我需要在每个过程的开头建立一个堆栈帧

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

4.) 在每个过程返回之前从堆栈帧中弹出寄存器

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

这些东西解决了我的问题。

【讨论】:

  • 如果在返回之前清理 x87 堆栈,则不需要 finit。 (例如,在两个flds 之后使用fmulp 而不是fmul。)返回x87 堆栈上的额外内容可能会导致代码中的其他地方崩溃。在这种情况下,finit 可以用作解决方法,因为您的程序很简单。
  • 无论如何,很高兴您能够找到并解决缺少ret 的问题。
猜你喜欢
  • 1970-01-01
  • 2015-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-31
  • 1970-01-01
  • 2011-04-29
  • 1970-01-01
相关资源
最近更新 更多