float[] 数组的平均值(Intel 8086)

Average of float[] array (Intel 8086)

我正在尝试将我的 ANSI C 代码与 ASM(准确地说是 TASM)模块结合起来。
我决定选择经典任务 - 获取数组中数字的平均值,它几乎可以正常工作,它编译和链接成功,但最后它说平均值等于 -0(当它不等于 -0)时。

我做错了什么?这是我的 .c 代码中需要的部分:

#include <stdio.h>
extern float avg(int, float*);

int main()
{
  int n = 2;
  float tab[] = {2.0, 3.0};
  printf("%.3g\n", avg(n, tab));

  return 0;
}

.asm程序:

avg PROC
    finit
    push BP
    mov BP, SP

    push bx
    mov cx, [bp+4]      ; no of elements
    mov bx, [bp+8]      ; address

    fldz ; zero
    jcxz avg_end ; if cx==0, end

    iter:
    fadd DWORD PTR [bx]
    add bx, 4
    loop iter

    fidiv DWORD PTR [bp+4] ; sum/n

    avg_end:
    pop bx
    pop BP
    ret
avg ENDP

我的程序内部还有一个外部函数,而且运行良好。
唯一的问题必须在 avg PROC 代码内部。我会很感激你的想法!

在实地址模式下,指针不仅仅是一个偏移量。所以要获取第二个参数 float* 你需要:

lds bx, [bp+8]      ;full pointer

您可能想要 push ds/pop ds

第一个参数是双字吗?你可以试试:

fidiv WORD PTR [bp+4] ; sum/n

为什么你从不从 FP 堆栈中弹出任何东西?

您至少在 returning 之前缺少最后一个 fstp DWORD PTR [bp]。分别在您的 ABI 希望将 return 值写入的任何位置。

目前你正在推送到 FP 堆栈,计算平均值,仅此而已。你泄露了一个寄存器,却从未看过结果。

我明白了。看来我在那里遇到了两个问题:

  • 首先——寻址。
    bx 寄存器应填写 [bp+6] 而不是 [bp+8].
    这很明显,因为我的第一个 arg 是整数,2B 长,不是吗?

  • 除此之外,@Sep Roland 对我的 fidiv 指示是正确的。
    我的值甚至不是 DWORD,它只是 WORD,它解决了我所有的问题。

现在可以使用了,谢谢大家的宝贵时间。
我无法删除我的问题,所以我发布了我的答案,也许有一天它会有用。