mtszkw
mtszkw

Reputation: 2783

Average of float[] array (Intel 8086)

I'm trying to combine my ANSI C code with ASM (TASM to be precise) module.
I decided to choose the classic task - get average of numbers in array, and it is almost working, it compiles and links successfully, but at the end it says that average equals -0 (when it does not).

What did I do wrong? Here's the needed part of my .c code:

#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;
}

And .asm procedure:

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

My program has also one more extern function inside and it works well.
The only problem has to be inside avg PROC code. I'd appreciate your ideas!

Upvotes: 0

Views: 331

Answers (3)

mtszkw
mtszkw

Reputation: 2783

I got it. It seems I had two problems there:

  • First of all - addressing.
    bx register should be filled with [bp+6] instead of [bp+8].
    That's obvious, because my first arg is integer, 2B long, isn't it?

  • In addition to that, @Sep Roland was right with my fidiv instruction.
    My value is not even DWORD, it's only WORD and it fixes all my problems.

It works now, thank you all for your time.
I couldn't delete my question, so I'm posting my answer, maybe it'll be useful someday.

Upvotes: 0

Ext3h
Ext3h

Reputation: 6393

Why are you never popping anything from the FP stack?

You are at least missing a final fstp DWORD PTR [bp] prior to returning. Respectively whereever your ABI wants the return value written to.

Currently you are pushing to the FP stack, calculating the average, and that's it. You've leaked a register and never looked at the result.

Upvotes: 1

Sep Roland
Sep Roland

Reputation: 39166

In the real address mode a pointer won't be just an offset. So to fetch the 2nd argument float* you would need:

lds bx, [bp+8]      ;full pointer

You might want to push ds/pop ds.

Is the 1st argument even a dword? You might try:

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

Upvotes: 3

Related Questions