2016-05-08 10 views
0

私はANSI CコードをASM(正確にはTASM)モジュールと組み合わせようとしています。
私は古典的な仕事を選ぶことに決めました - 配列の数値の平均を得て、それはほとんど働いており、コンパイルとリンクは成功しましたが、最後には平均が-0に等しいと言います。フロートの平均[]配列(インテル8086)

どうしたのですか?

#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手順:ここに私の.Cコードの必要な部分だ

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 

私のプログラムは、1以上のextern関数の内部でもあり、それがうまく動作します。
唯一の問題は、avg PROCコード内になければなりません。私はあなたのアイデアを感謝します!

+1

なぜbxに8が追加されましたか?あなたの環境の 'float'が8バイトだと確信していますか? – MikeCAT

+0

実際には16ビットのDOSプログラムを書いていますか?もしそうなら、なぜですか? – zwol

+1

16ビット環境で引数間にオフセット4を使用すると、奇妙に見えます。あなたのABIに沿っていると確信していますか? – MikeCAT

答えて

0

私はそれを得ました。そこには2つの問題があったようです。

  • まずはアドレッシング。
    bxレジスタは、[bp+8]の代わりに[bp+6]と入力する必要があります。
    私の最初の引数は整数なので、それは明らかです。

  • さらに、@Sep Rolandは私のfidiv命令で正しくありました。
    私の価値はDWORDでさえありません。それはただの言葉であり、私のすべての問題を解決します。

これで動作します。お時間をいただきありがとうございます。
私の質問を削除できませんでしたので、私の回答を掲載しています。おそらくいつか役立つかもしれません。

3

実アドレスモードでは、ポインタは単なるオフセットではありません。だから、あなたが必要となる第2引数フロート*をフェッチします

lds bx, [bp+8]  ;full pointer 

あなたがpush ds/pop dsする場合があります。

第1引数もdwordですか?試してみてください:

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

なぜFPスタックから何かが飛び出すことはありませんか?

返品に先立ち、少なくとも最終的にfstp DWORD PTR [bp]がありません。あなたのABIは、返された価値を書こうと思っています。

現在、FPスタックにプッシュして平均を計算しています。それだけです。あなたはレジスタを漏らして、結果を見たことはありません。

+0

私が知る限り、浮動小数点値を返すと、結果はFPUスタック 'st(0)'の先頭に置かれます。それはそうじゃないの? – 5208760

+1

コンパイラが選択したABIに依存します。 'hardfp'対' softfp'です。後者は、通常のスタック/レジスタにパラメータと戻り値を渡します。最初のスタックはFPスタック上のすべてのFPパラメータと戻り値をプッシュして返します。 'cdecl' ABIでのみ' st(0) 'が返されます。 – Ext3h

関連する問題