汇编 - 收到浮点异常

Posted

技术标签:

【中文标题】汇编 - 收到浮点异常【英文标题】:Assembly - Floating Point Exception Received 【发布时间】:2015-07-23 01:49:29 【问题描述】:

我正在尝试编写一个计算下载时间的程序,但我一直在输出时收到“浮点异常”错误。感谢任何帮助,因为我已经尝试调试此代码很长一段时间,但根本无法识别问题。在做了一些研究之后,我认为问题在于发生除法的位置,因为商无法放入 eax 寄存器中,但据我所知。

%include "asm_io.inc"
segment .data 
prompt1         db  "Enter the unit for file size: ", 0
prompt2         db  "Enter the unit for throughput: ", 0
prompt3         db  "Enter the file size: ", 0
prompt4         db  "Enter the througput: ", 0
outputformat    db  "The time would be %d seconds.", 10, 0

segment .bss 

segment .text
    global  asm_main
    extern printf
asm_main:
    enter   0,0               ; setup routine
    pusha
;***************CODE STARTS HERE***************************
mov eax, prompt1            ; move prompt1 into eax for display
call    print_string            ; display prompt 1
call    read_char           ; read file size unit from user
call    read_char
push    eax             ; store file size unit on stack @ ebp+20

mov eax, prompt2            ; move prompt2 into eax for display
call    print_string            ; display prompt 2
call    read_char           ; read  throughput unit from user
call    read_char
push    eax             ; store throughput unit on stack @ ebp+16

mov eax, prompt3            ; move prompt3 into eax for display
call    print_string            ; display prompt 3
call    read_int            ; read file size from user
push    eax             ; store file size on stack @ ebp+12

mov eax, prompt4            ; move prompt4 into eax for display
call    print_string            ; display prompt4
call    read_int            ; read throughput from user
push    eax             ; store throughput unit on stack @ ebp+8

call    dl_time             ; call custom function to calc download time
add esp, 16             ; remove parameters from stack

push    eax             ; push download time onto stack for printf
push    outputformat            ; push format for printf function onto stack

call    printf              ; display formatted output
add esp, 8

;***************CODE ENDS HERE*****************************
    popa
    mov     eax, 0            ; return back to C
    leave                     
    ret

; function dl_time
; returns the download time for given file
; unisnged int dl_time( char fs_unit, char speed_unit, int file_size, int        conn_speed)
; parameters:
;   fs_unit     - unit for file size
;   tp_unit     - unit for connection speed
;   file_size   - file size
;   throughput  - connection speed
; return value:
;   download time for given file with given speed, in seconds floored

%define fs_unit     [ebp+20]
%define tp_unit     [ebp+16]
%define file_size   [ebp+12]
%define throughput  [ebp+8]

dl_time:
    enter   0,0             ; make room for speed and size on stack
    push    ebx             ; store value of ebx
    push    ecx             ; store value of ecx
    push    edx             ; store value of edx

    mov edx, 'B'
    cmp edx, fs_unit            ; if file size unit is byte
    jz  fs_B

    mov edx, 'K'
    cmp edx, fs_unit            ; if file size unit is kilobyte
    jz  fs_K

    mov edx, 'M'
    cmp edx, fs_unit            ; if file size unit it megabyte
    jz  fs_M

fs_B:
    ;imul   eax, file_size, 1024        ; calculate file size in bits
    sal file_size, 10
    jmp after_fs
fs_K:
    ;imul   eax, file_size, 1024
    ;imul   eax, 1024           ; calculate file size in bits
    sal file_size, 20
    jmp after_fs
fs_M:
    ;imul   eax, file_size, 1024
    ;imul   eax, 1024
    ;imul   eax, 1024           ; calculate file size in bits
    sal file_size, 30

after_fs:
    mov edx, 'B'
    cmp edx, tp_unit            ; if throughput unit is bits per second
    jz  after_tp

    mov edx, 'K'
    cmp edx, tp_unit            ; if throughput unit is kilobits per second
    jz  tp_K

    mov edx, 'M'
    cmp edx, tp_unit            ; if throughput unit is megabits per second
    jz  tp_M

tp_K:
    ;imul   ebx, throughput, 1024       ; convert kilobits to bits
    sal throughput, 10
    jmp after_tp
tp_M:
    ;imul   ebx, throughput, 1024       ; convert megabits to bits
    ;imul   ebx, 1024
    sal throughput, 20

after_tp:
    xor edx, edx            ; clear edx for division
    mov eax, file_size
    mov ebx, throughput
    div ebx             ; divide file size by throughput
    mov ecx, 128            ; move 128 into ecx for division
    div ecx             ; divide quotient by 128 to arive at download time

pop ebx
pop ecx
pop edx
leave
ret

谢谢

【问题讨论】:

您可以使用调试器单步执行您的代码,并查看异常发生前寄存器中的内容。 ***.com/tags/x86/info 【参考方案1】:

你没有在第二除法之前清除edx

div ebx             ; divide file size by throughput
; EDX WILL NOW BE SET TO EAX % EBX (I.E. THE REMAINDER)
mov ecx, 128            ; move 128 into ecx for division
; THERE SHOULD BE AN XOR EDX,EDX HERE
div ecx             ; divide quotient by 128 to arive at download time

【讨论】:

谢谢你。我发现问题的根源在于我不断变化的逻辑。当我将file_size移位超过7位时,EAX的值变为0。我不确定在移位之前如何确保file_size是双字。

以上是关于汇编 - 收到浮点异常的主要内容,如果未能解决你的问题,请参考以下文章

浮点异常(Core Dumped)在汇编时进行除法

为啥我会收到“浮点异常(核心转储)”?

浮点异常程序集 64 位

(C++)我正在尝试从文本文件中读取和输出随机行,并且在运行它时不断收到“浮点异常(核心转储)”

汇编代码还原第一讲,基本类型以及浮点编码.

浮点 汇编指令基础知识