【问题标题】:Harmonic Average Yields incorrect Result谐波平均产生不正确的结果
【发布时间】:2014-12-03 22:30:29
【问题描述】:

作为一项家庭作业,我们需要使用由 C 程序驱动的汇编程序来计算调和平均值。

我们使用的是 64 位 linux 机器,需要使用 64 位浮点数。

我是大会的新手。对于任何不良的编码习惯或我的代码完全错误,我深表歉意。


代码的问题是结果仅返回以浮点格式输入的最后一个数字。我不知道错误发生在哪里,虽然我相信它在于addDen 函数。

例如:如果您要输入数字 5、6、7、8,结果将返回 8.0000。

这是我的汇编程序代码:

;Assembly function that computs the harmonic mean
;of an array of 64-bit floating-point numbers.
;Retrieves input using a C program.
;
;Harmonic mean is defined as Sum(n/((1/x1) + (1/x2) + ... + (1/xn)))
;
;   expects:
;       RDI - address of array
;       RSI - length of the array
;   returns
;       XMMO - the harmonic average of array's values

global harmonicMean

section .data
    Zero dd 0.0
    One dd 1.0

section .text
    harmonicMean:
        push rbp
        mov rbp, rsp                    ;C prologue

        movss xmm10, [Zero]     ;Holds tally of denominator
        cvtsi2ss xmm0, rsi      ;Take length and put it into xmm0 register

        .whileLoop:
            cmp rsi, 0                  ;Is the length of array 0?
            je .endwhile
            call addDen                 ;Compute a denominator value and add it to sum
            add rdi, 4                  ;Add size of float to address
            dec rsi                         ;Decrease the length
            jmp .whileLoop
        .endwhile:

        divss xmm0, xmm10

        leave
        ret


    ;Calculates a number in the denominator
    addDen:
        push rdi
        movss xmm8, [One]
        movss xmm9, [rdi]
        divss xmm8, xmm9
        addss xmm10, xmm8
        pop rdi
        ret

为了重现逻辑错误,我还将包括我的驱动程序:

/*
* Harmonic Mean Driver
* Tyler Weaver
* 03-12-2014
*/
#include<stdio.h>

#define ARRAYSIZE 4

double harmonicMean(double *, unsigned);

int main(int argc, char **argv) {
    int i;
    double ary[ARRAYSIZE];
    double hm;

    printf("Enter %d f.p. values: ", ARRAYSIZE);

    for (i = 0; i < ARRAYSIZE; i++) {
        scanf(" %lf", &ary[i]);
    }

    hm = harmonicMean(ary, ARRAYSIZE);
    printf("asm: harmonic mean is %lf\n", hm);

    return 0;
}

任何帮助将不胜感激!

【问题讨论】:

  • double *unsigned 的大小是否与 RDIRSI 的大小相同?建议printf("%zu %zu\n", sizeof (double*), sizeof (unsigned));验证。
  • 它们应该分别是 4 个字节。我们被告知对驱动程序使用双重和无符号。在任务详情中。我是Assembly的新手,所以我不知道这是否会溢出寄存器。数组会更长,但 RDI 寄存器应该只保存数组的前 4 个字节。
  • 同意应该每个都是4个字节。 C 代码是否使用printf("%zu %zu\n", sizeof (double*), sizeof (unsigned)); 报告?
  • 1) 我怀疑“RDI 寄存器应该只保存数组的前 4 个字节”。 RDI 应该保存数组的地址。 2) 为什么add rdi, 4 ;Add size of float to address double 通常是 8 个字节?
  • 是的,floatdouble 之间似乎存在混淆。你传入一个双精度数组,但几乎所有的 asm 代码都需要浮点数:你使用 ss 指令,假设大小为 4,你也返回一个浮点数。

标签: c linux assembly 64-bit average


【解决方案1】:

是的,floatdouble 之间似乎存在混淆。你传入一个双精度数组,但几乎所有的 asm 代码都需要浮点数:你使用 ss 指令,假设大小为 4,你也返回一个浮点数。 ——小丑

浮点数和双精度数存在问题!我真的很感谢你的两个回答。我很困惑,因为讲师告诉我们在汇编程序中使用浮点数,而他在示例驱动程序中使用了双精度数。我和教练谈过,他已经确定了他的指示。我再次感谢你! ——泰勒·韦弗

【讨论】:

    【解决方案2】:
    here is the algorithm, is a mix between C and pseudo code
    My suggestion is to write this program in C.
    Then have the compiler output the related asm language
    then use that asm output as a guide in writing your own program
    
    ! ----------------------------------------------------------
    ! This program reads a series of input data values and 
    ! computes their arithmetic, geometric and harmonic means.
    ! Since geometric mean requires taking n-th root, all input
    ! data item must be all positive (a special requirement of
    ! this program , although it is not absolutely necessary).
    ! If an input item is not positive, it should be ignored.
    ! Since some data items may be ignored, this program also
    ! checks to see if no data items remain!
    ! ----------------------------------------------------------
    
    PROGRAM   ComputingMeans
       IMPLICIT  NONE
    
       REAL    :: X
       REAL    :: Sum, Product, InverseSum
       REAL    :: Arithmetic, Geometric, Harmonic
       INTEGER :: Count, TotalNumber, TotalValid
    
       Sum        = 0.0                     ! for the sum
       Product    = 1.0                     ! for the product
       InverseSum = 0.0                     ! for the sum of 1/x
       TotalValid = 0                       ! # of valid items
    
       READ(*,*)  TotalNumber               ! read in # of items
       DO Count = 1, TotalNumber            ! for each item ...
          READ(*,*)  X                      ! read it in
          WRITE(*,*) 'Input item ', Count, ' --> ', X
          IF (X <= 0.0) THEN                ! if it is non-positive
             WRITE(*,*) 'Input <= 0.  Ignored'   ! ignore it
          ELSE                              ! otherwise,
             TotalValid = TotalValid + 1    ! count it in
             Sum        = Sum + X           ! compute the sum,
             Product    = Product * X       ! the product
             InverseSum = InverseSum + 1.0/X     ! and the sum of 1/x
          END IF
       END DO
    
       IF (TotalValid > 0) THEN             ! are there valid items?
          Arithmetic = Sum / TotalValid     ! yes, compute means
          Geometric  = Product**(1.0/TotalValid)
          Harmonic   = TotalValid / InverseSum
    
          WRITE(*,*)  'No. of valid items --> ', TotalValid
          WRITE(*,*)  'Arithmetic mean    --> ', Arithmetic
          WRITE(*,*)  'Geometric mean     --> ', Geometric
          WRITE(*,*)  'Harmonic mean      --> ', Harmonic
       ELSE                                 ! no, display a message
          WRITE(*,*)  'ERROR: none of the input is positive'
       END IF
    
    END PROGRAM  ComputingMeans
    

    【讨论】:

    • 这不是汇编代码,这是原始问题所要求的
    猜你喜欢
    • 2020-12-14
    • 2015-10-12
    • 2015-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多