sprintf関数の動作が変です

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
およよ

sprintf関数の動作が変です

#1

投稿記事 by およよ » 14年前

Cygwin GCC で newlib のlibc, libm をリンクしています。
ソース中の GCON_putstrL() は液晶ディスプレイを標準出力とする、
puts()ライクな関数です。

コード:

/* 元のソースは大きすぎるので簡略 */
#include <stdio.h>
#include <float.h>
int main(void){
    int x;
    x = 7;
    char buf[100];
    sprintf(buf, "%d", x);
    GCON_putstrL(buf, 10); //第二引数は表示文字数指定
    return 0;
}
このコードを実行すると、標準出力に 7 を表示すべきところ
-124276553 を表示します。

なお
buf = "hoge";
GCON_putstrL(buf, 10);
のように、文字列を指定すると、問題なく表示します。

何度見直しても書式は正しいはずなのですが、
なぜ表示がおかしくなるのかわかりません。

やりたいことは、浮動小数点の変数 %f を char 型のbuf に
格納することです。それができればsprintf()を諦めても構いません。

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: sprintf関数の動作が変です

#2

投稿記事 by h2so5 » 14年前

sprintfの書式指定が間違っています。

私の勘違いでした。申し訳ありません。

およよ さんが書きました: やりたいことは、浮動小数点の変数 %f を char 型のbuf に
格納することです。それができればsprintf()を諦めても構いません。
sprintfに渡している x はintになっているようですが。

およよ

Re: sprintf関数の動作が変です

#3

投稿記事 by およよ » 14年前

当初ここでつまづくとは思っていなかったので、
%f でやったのですが、うまくいきませんでした。

内部のキャストに問題があるのかも知れないと思い、
%d でうまくいくことを確認しようとした次第です・・・

dic
記事: 658
登録日時: 14年前
住所: 宮崎県
連絡を取る:

Re: sprintf関数の動作が変です

#4

投稿記事 by dic » 14年前

8行と9行の間で buf の内容を確認してみてください

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: sprintf関数の動作が変です

#5

投稿記事 by softya(ソフト屋) » 14年前

たしかに変ですね。
マイコンの場合、スタックが足らないとprintf系の動作が異常になるいうのを聞いたことがあるので疑ってみてください。
あとはnewlibのmake時の指定がどうなっているかとか、実装問題と絡むのでそちらも調べてみる必要があると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

およよ

Re: sprintf関数の動作が変です

#6

投稿記事 by およよ » 14年前

念のため作った Makefile も示します。

コード:

CSRCS    = app.c
TARGET   = app
ASMSRCS  = startup.s
OBJS     = $(ASMSRCS:%.s=%.o) $(CSRCS:%.c=%.o)
LDSCRIPT = memory.def

GCC = /usr/local/sh-tools/bin/sh-elf-gcc
LD = /usr/local/sh-tools/bin/sh-elf-ld
AS = /usr/local/sh-tools/bin/sh-elf-as
OBJCOPY = /usr/local/sh-tools/bin/sh-elf-objcopy
GCCLIB = /usr/local/sh-tools/lib/gcc/sh-elf/4.4.0/m2a
NEWLIB_INC = /usr/local/sh-tools/newlib/sh-elf/include
NEWLIB_LIB = /usr/local/sh-tools/newlib/sh-elf/lib/m2a

all: $(OBJS) $(LDSCRIPT)
	$(LD) -Map $(TARGET).map -T $(LDSCRIPT) $(OBJS) -L$(NEWLIB_LIB) -L$(GCCLIB) -lc -lm -lgcc -o $(TARGET).elf
	$(OBJCOPY) -O srec $(TARGET).elf $(TARGET).mot
	$(OBJCOPY) -O binary $(TARGET).elf $(TARGET).bin
.c.o:
	$(GCC) -c -g -m2a -I$(NEWLIB_INC) $<
.s.o: 
	$(AS) $< -g -o $@
clean:
	rm *.o $(TARGET).elf $(TARGET).map $(TARGET).mot $(TARGET).bin
ご指摘のスタックについても、これから調べてみます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: sprintf関数の動作が変です

#7

投稿記事 by softya(ソフト屋) » 14年前

newlib自体のmakeはどうされました?

[追記]
すいません、これから出かけるので返事が遅くなります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

およよ

Re: sprintf関数の動作が変です

#8

投稿記事 by およよ » 14年前

newlibはネット上にあった、ビルド済みGCCおよび各種ツール一式
sh-tools20100424.tar.bz2 を解凍したものです。
実はお仕着せのものだけあってちょっと気になっていましたので、
newlibを含めてgccを再インストールして確認します。
コンパイルしなおすので、しばらく時間がかかります。

およよ

Re: sprintf関数の動作が変です

#9

投稿記事 by およよ » 14年前

標準出力がTeraTerm のサンプルプログラムを作成し、
これで printf で変数の出力を確認すると、
int型は正常に表示されますが、
double型ですと NaN と表示されます。

理由はよくわかりませんが、更に調べています。
おそらく、 sprintf でも同じことが起こっていると思います。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: sprintf関数の動作が変です

#10

投稿記事 by softya(ソフト屋) » 14年前

およよ さんが書きました:標準出力がTeraTerm のサンプルプログラムを作成し、
これで printf で変数の出力を確認すると、
int型は正常に表示されますが、
double型ですと NaN と表示されます。

理由はよくわかりませんが、更に調べています。
おそらく、 sprintf でも同じことが起こっていると思います。
それだとfloat系のモジュールが有効ではないと思われます。
newlibのmakeからやり直さないと難しいかも知れません。

sprintfでintがおかしいのは別件なので再確認をお願いします。
floatをint表示しようとしたとかのミスではないですよね?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

およよ

Re: sprintf関数の動作が変です

#11

投稿記事 by およよ » 14年前

softya(ソフト屋) さんが書きました: sprintfでintがおかしいのは別件なので再確認をお願いします。
floatをint表示しようとしたとかのミスではないですよね?
Makefileとコード全体を見直し、int型だけは次のコードで動作するようになりました。
t_printf() は %c %s %d のみ表示可能なオリジナル関数です。
(最初に示したコードにあった GCON_putstrL() は、t_printf() 内部から呼び出した関数です。)
現在、Makefileは下記の様にしています。

コード:

#include <stdio.h>
#include <math.h>
#include <float.h>

int main(void){
  int x;
  char buf[100];
  x = 7;
  sprintf(buf, "%d", x);
  t_printf("%s\n", buf);
 return 0;
}
Makefile は次のようにしました。

コード:

CSRCS    = app.c
TARGET   = app
ASMSRCS  = startup.s
OBJS     = $(ASMSRCS:%.s=%.o) $(CSRCS:%.c=%.o)
LDSCRIPT = memory.def

GCC = /usr/local/sh-tools/bin/sh-elf-gcc
LD = /usr/local/sh-tools/bin/sh-elf-ld
AS = /usr/local/sh-tools/bin/sh-elf-as
OBJCOPY = /usr/local/sh-tools/bin/sh-elf-objcopy
GCCLIB = /usr/local/sh-tools/lib/gcc/sh-elf/4.4.0/m2a

NEWLIB_BASE=/usr/local/sh-tools/newlib/sh-elf
NEWLIB_INC = $(NEWLIB_BASE)/include
NEWLIB_LIB = $(NEWLIB_BASE)/lib

TARGET_SYSCALL_LIB_NAME = sh2a72623
TARGET_SYSCALL_LIB_DIR = ../lib

all: $(OBJS) $(LDSCRIPT)
	$(LD) -Map $(TARGET).map -T $(LDSCRIPT) $(OBJS) -L$(TARGET_SYSCALL_LIB_DIR) -L$(NEWLIB_LIB) -L$(GCCLIB) -l$(TARGET_SYSCALL_LIB_NAME) -lc -lm -lgcc -o $(TARGET).elf
	$(OBJCOPY) -O srec $(TARGET).elf $(TARGET).mot
	$(OBJCOPY) -O binary $(TARGET).elf $(TARGET).bin
.c.o:
	$(GCC) -c -m2a -I$(NEWLIB_INC) $<
.s.o: 
	$(AS) $< -o $@
clean:
	rm *.o $(TARGET).elf $(TARGET).map $(TARGET).mot $(TARGET).bin
ネット上の情報を頼りに、システムコール・ライブラリ sh2a72623.a を追加
した結果、とりあえずは、int型で動かないという問題は解決しました。
ただしGCC周りをいろいろいじったので、他に要因があったかも知れません。

キャストの受け渡しでトラブルを起こさないよう、それなりに意識しています(汗)。

およよ

Re: sprintf関数の動作が変です

#12

投稿記事 by およよ » 14年前

いまさらながらちょっと信じられないのですが、
newlib配下にfloat.hが見つかりません。もともとなかったのか、
環境を再構築したためになくなったのか今や不明ですが。

#include <float.h> はいったいどこを参照しているのでしょうか?
同じディレクトリには newlib.h なるヘッダあるのですが、これは何でしょうか?
関連するライブラリを再コンパイルして、様子をみなくてはならないのでしょうか?
疑問が噴出してきました。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: sprintf関数の動作が変です

#13

投稿記事 by softya(ソフト屋) » 14年前

およよ さんが書きました:いまさらながらちょっと信じられないのですが、
newlib配下にfloat.hが見つかりません。もともとなかったのか、
環境を再構築したためになくなったのか今や不明ですが。

#include <float.h> はいったいどこを参照しているのでしょうか?
同じディレクトリには newlib.h なるヘッダあるのですが、これは何でしょうか?
関連するライブラリを再コンパイルして、様子をみなくてはならないのでしょうか?
疑問が噴出してきました。
float.hはC言語の標準ライブラリです。
newlib.hは分かりません。
newlibは扱ったことがないのでmakeでどうすれば良いのかが掴めないのと、gdbでアセンブラレベルで追いかけるしか無いかも知れません。申し訳ない。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

およよ

Re: sprintf関数の動作が変です

#14

投稿記事 by およよ » 14年前

数ある疑問はさておいて・・・ネットで検索してみると、
マイコンのようなリソースの不足するシステムで、
%f を扱える sprintf() または互換の関数は実質的に
ないのか皆苦労しているようです。

どうやら解決は遠いようですね、とはいえこのままでは
埒が明かないので、時間をかけて調べてみます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: sprintf関数の動作が変です

#15

投稿記事 by softya(ソフト屋) » 14年前

newlibのソースを見る限りprintf/sprintfは浮動小数点には対応しているように見えます。
ただ、引数の受け渡しが的確に行われているかはアセンブルコードを見てみないとなんとも言えません。
その前にSH2のアセンブラを完全に忘れているのでスタックフレームを追いかける自信もない(汗)。
最後がセガ・サターンのSH2で、しかもほとんどアセンブラで組んでませんでしたから。

[追記]
2008年3月号記事 「SH-2/V850マイコン基板向け浮動小数点演算プログラムの作成」
http://www.cqpub.co.jp/interface/download/contents.htm
ってのがあるんですが、該当号のインターフェイスを持っていないので中身がざっとしか分かりませんが文字列変換もあるようです。
ただし、SH2Aでは無いのでFPUを持たないSH2用です。参考程度で。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

およよ

Re: sprintf関数の動作が変です

#16

投稿記事 by およよ » 14年前

毎度的確なアドバイス痛み入ります。
ご指摘のソースコードは、interfaceのダウンロード・ページから入手しました。
アーカイブの内容を確認してみます。

組み込み向けに %f を char に変換する ftoa() を自作される方
が国内外にいらっしゃるようです、今こちらを調べています。

およよ

Re: sprintf関数の動作が変です

#17

投稿記事 by およよ » 14年前

とりあえず、tiny な printf/sprintf で %f が使えない場合に
%s と %d だけを使って浮動小数点を表示するコードを考えてみました。
もちろん内部では正しく浮動小数点が演算されていることが前提です。

コード:

#include <stdio.h>
#include <math.h>

char *t_ftoa(double f1){
	int d1, d2, d3, sign;
	double f2, f3;
	static char buf[100];
	
	sign = signbit(f1);
	if(sign != 0) f1 = fabs(f1);
	d1 = f1; /* 実数部分 */
	f2 = f1 - d1;/* 小数全体 */
	d2 = (int)(f2 * 10000);/* 小数第1位~4位 */
	f3 = f2 * 10000 - d2;
	d3 = (int)(f3 * 1000 + 0.5);/* 小数第5位~7位(四捨五入) */
	if(sign == 0){
		sprintf(buf,  "%d.%04d%03d\n", d1, d2, d3);
	}else{
		sprintf(buf, "-%d.%04d%03d\n", d1, d2, d3);
	}
	return buf;
}

int main(void){
	char *p;
	double num;
	num = 4321.1234567; 
	p = t_ftoa(num);
/*
	printf("num(%%f) = %.7f\n", num);
*/
	printf("buf(%%s) = %s\n", p);
	return 0;
}
このコードによって、浮動小数点の内部演算
そのものに問題があることが分かりました(泣)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: sprintf関数の動作が変です

#18

投稿記事 by softya(ソフト屋) » 14年前

FPUがちゃんと動作していない可能性が高いですね。
そのソースコードで-Sオプションでアセンブルコードを出してみてもらえませんか?
そして、出力された.sファイルのアセンブルコードを貼ってください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

およよ

Re: sprintf関数の動作が変です

#19

投稿記事 by およよ » 14年前

app.c の アセンブルコードです。

コード:

	.file	"app.c"
	.text
	.section	.rodata
	.align 2
.LC0:
	.string	"Start of Code.\n"
	.align 2
.LC1:
	.string	"sign = %d\n"
	.align 2
.LC2:
	.string	"d1 = %d\n"
	.align 2
.LC3:
	.string	"d2 = %d\n"
	.align 2
.LC4:
	.string	"d3 = %d\n"
	.align 2
.LC5:
	.string	"\nEnd Of Code.\n"
	.text
	.align 1
	.global	_main
	.type	_main, @function
_main:
	mov.l	r14,@-r15
	sts.l	pr,@-r15
	add	#-60,r15
	mov	r15,r14
	mov.l	.L21,r1
	jsr/n	@r1
	mov.l	.L22,r1
	jsr/n	@r1
	mov.l	.L23,r1
	jsr/n	@r1
	mov.l	.L24,r1
	jsr/n	@r1
	mov	r14,r1
	add	#-4,r1
	mov.l	.L25,r2
	mov.l	r2,@(12,r1)
	mov	r14,r1
	add	#-4,r1
	mov	#0,r2
	mov.l	r2,@(8,r1)
	bra	.L2
	nop
	.align 1
.L13:
	mov	r14,r1
	add	#-4,r1
	mov	#0,r2
	mov.l	r2,@(4,r1)
	bra	.L3
	nop
	.align 1
.L12:
	mov	r14,r1
	add	#-4,r1
	mov.l	@(4,r1),r2
	mov	#39,r1
	cmp/gt	r1,r2
	bt	.L4
	mov	r14,r1
	add	#-4,r1
	mov.l	@(12,r1),r1
	mov	#0,r2
	mov.w	r2,@r1
	mov	r14,r1
	add	#-4,r1
	mov	r14,r2
	add	#-4,r2
	mov.l	@(12,r2),r2
	add	#2,r2
	mov.l	r2,@(12,r1)
	bra	.L5
	nop
	.align 1
.L4:
	mov	r14,r1
	add	#-4,r1
	mov.l	@(4,r1),r2
	mov	#79,r1
	cmp/gt	r1,r2
	bt	.L6
	mov	r14,r1
	add	#-4,r1
	mov.l	@(12,r1),r1
	mov	#31,r2
	mov.w	r2,@r1
	mov	r14,r1
	add	#-4,r1
	mov	r14,r2
	add	#-4,r2
	mov.l	@(12,r2),r2
	add	#2,r2
	mov.l	r2,@(12,r1)
	bra	.L5
	nop
	.align 1
.L6:
	mov	r14,r1
	add	#-4,r1
	mov.l	@(4,r1),r2
	mov	#119,r1
	cmp/gt	r1,r2
	bt	.L7
	mov	r14,r1
	add	#-4,r1
	mov.l	@(12,r1),r1
	mov.w	.L26,r2
	mov.w	r2,@r1
	mov	r14,r1
	add	#-4,r1
	mov	r14,r2
	add	#-4,r2
	mov.l	@(12,r2),r2
	add	#2,r2
	mov.l	r2,@(12,r1)
	bra	.L5
	nop
	.align 1
.L7:
	mov	r14,r1
	add	#-4,r1
	mov.l	@(4,r1),r2
	movi20	#159,r1
	cmp/gt	r1,r2
	bt	.L8
	mov	r14,r1
	add	#-4,r1
	mov.l	@(12,r1),r1
	mov.w	.L27,r2
	mov.w	r2,@r1
	mov	r14,r1
	add	#-4,r1
	mov	r14,r2
	add	#-4,r2
	mov.l	@(12,r2),r2
	add	#2,r2
	mov.l	r2,@(12,r1)
	bra	.L5
	nop
	.align 1
.L8:
	mov	r14,r1
	add	#-4,r1
	mov.l	@(4,r1),r2
	movi20	#199,r1
	cmp/gt	r1,r2
	bt	.L9
	mov	r14,r1
	add	#-4,r1
	mov.l	@(12,r1),r1
	mov.w	.L28,r2
	mov.w	r2,@r1
	mov	r14,r1
	add	#-4,r1
	mov	r14,r2
	add	#-4,r2
	mov.l	@(12,r2),r2
	add	#2,r2
	mov.l	r2,@(12,r1)
	bra	.L5
	nop
	.align 1
.L9:
	mov	r14,r1
	add	#-4,r1
	mov.l	@(4,r1),r2
	movi20	#239,r1
	cmp/gt	r1,r2
	bt	.L10
	mov	r14,r1
	add	#-4,r1
	mov.l	@(12,r1),r1
	mov.w	.L29,r2
	mov.w	r2,@r1
	mov	r14,r1
	add	#-4,r1
	mov	r14,r2
	add	#-4,r2
	mov.l	@(12,r2),r2
	add	#2,r2
	mov.l	r2,@(12,r1)
	bra	.L5
	nop
	.align 1
.L10:
	mov	r14,r1
	add	#-4,r1
	mov.l	@(4,r1),r2
	movi20	#279,r1
	cmp/gt	r1,r2
	bt	.L11
	mov	r14,r1
	add	#-4,r1
	mov.l	@(12,r1),r1
	mov	#-32,r2
	mov.w	r2,@r1
	mov	r14,r1
	add	#-4,r1
	mov	r14,r2
	add	#-4,r2
	mov.l	@(12,r2),r2
	add	#2,r2
	mov.l	r2,@(12,r1)
	bra	.L5
	nop
	.align 1
.L26:
	.short	2016
.L27:
	.short	2047
.L28:
	.short	-2048
.L29:
	.short	-2017
.L30:
	.align 2
.L21:
	.long	_CPU_BusInitialize
.L22:
	.long	_CPU_UartInitialize
.L23:
	.long	_GRPH_Initialize
.L24:
	.long	_GCON_Initialize
.L25:
	.long	1007124480
	.align 1
.L11:
	mov	r14,r1
	add	#-4,r1
	mov.l	@(12,r1),r1
	mov	#-1,r2
	mov.w	r2,@r1
	mov	r14,r1
	add	#-4,r1
	mov	r14,r2
	add	#-4,r2
	mov.l	@(12,r2),r2
	add	#2,r2
	mov.l	r2,@(12,r1)
.L5:
	mov	r14,r1
	add	#-4,r1
	mov	r14,r2
	add	#-4,r2
	mov.l	@(4,r2),r2
	add	#1,r2
	mov.l	r2,@(4,r1)
.L3:
	mov	r14,r1
	add	#-4,r1
	mov.l	@(4,r1),r2
	movi20	#319,r1
	cmp/gt	r1,r2
	bt	.L54
	bra	.L12
	nop
.L54:
	mov	r14,r1
	add	#-4,r1
	mov	r14,r2
	add	#-4,r2
	mov.l	@(8,r2),r2
	add	#1,r2
	mov.l	r2,@(8,r1)
.L2:
	mov	r14,r1
	add	#-4,r1
	mov.l	@(8,r1),r2
	mov	#119,r1
	cmp/gt	r1,r2
	bt	.L53
	bra	.L13
	nop
.L53:
	mov	r14,r1
	add	#-4,r1
	mov	#0,r2
	mov.l	r2,@(8,r1)
	bra	.L14
	nop
	.align 1
.L17:
	mov	r14,r1
	add	#-4,r1
	mov	#0,r2
	mov.l	r2,@(4,r1)
	bra	.L15
	nop
	.align 1
.L16:
	mov	r14,r1
	add	#-4,r1
	mov.l	@(4,r1),r1
	movi20	#248,r0
	and	r0,r1
	shar	r1
	shar	r1
	shar	r1
	shll8	r1
	add	r1,r1
	shll2	r1
	exts.w	r1,r2
	mov	r14,r1
	add	#-4,r1
	mov.l	@(4,r1),r1
	movi20	#252,r3
	and	r3,r1
	shar	r1
	shar	r1
	shll2	r1
	add	r1,r1
	shll2	r1
	exts.w	r1,r1
	or	r2,r1
	exts.w	r1,r2
	mov	r14,r1
	add	#-4,r1
	mov.l	@(4,r1),r1
	movi20	#248,r0
	and	r0,r1
	shar	r1
	shar	r1
	shar	r1
	exts.w	r1,r1
	or	r2,r1
	exts.w	r1,r1
	extu.w	r1,r2
	mov	r14,r1
	add	#-4,r1
	mov.l	@(12,r1),r1
	mov.w	r2,@r1
	mov	r14,r1
	add	#-4,r1
	mov	r14,r2
	add	#-4,r2
	mov.l	@(12,r2),r2
	add	#2,r2
	mov.l	r2,@(12,r1)
	mov	r14,r1
	add	#-4,r1
	mov	r14,r2
	add	#-4,r2
	mov.l	@(4,r2),r2
	add	#1,r2
	mov.l	r2,@(4,r1)
.L15:
	mov	r14,r1
	add	#-4,r1
	mov.l	@(4,r1),r2
	movi20	#319,r1
	cmp/gt	r1,r2
	bf	.L16
	mov	r14,r1
	add	#-4,r1
	mov	r14,r2
	add	#-4,r2
	mov.l	@(8,r2),r2
	add	#1,r2
	mov.l	r2,@(8,r1)
.L14:
	mov	r14,r1
	add	#-4,r1
	mov.l	@(8,r1),r2
	mov	#119,r1
	cmp/gt	r1,r2
	bf	.L17
	mov	r14,r1
	add	#-4,r1
	mov.l	.L31,r2
	mov.l	r2,@(12,r1)
	mov.l	.L32,r1
	mov	r1,r4
	mov.l	.L49,r1
	jsr/n	@r1
	mov	r14,r3
	add	#28,r3
	mov.l	.L34,r1
	mov.l	.L35,r2
	mov.l	r1,@r3
	mov.l	r2,@(4,r3)
	mov	r14,r3
	add	#52,r3
	mov	r14,r1
	add	#28,r1
	mov.l	@(4,r1),r2
	mov.l	@r1,r1
	mov.l	r1,@r3
	mov.l	r2,@(4,r3)
	mov	r14,r1
	add	#52,r1
	fmov.d	@r1,dr4
	mov.l	.L36,r1
	jsr/n	@r1
	mov	r0,r1
	mov	r1,r2
	mov	r14,r1
	add	#-4,r1
	mov.l	r2,@(16,r1)
	mov.l	.L37,r2
	mov	r14,r1
	add	#-4,r1
	mov.l	@(16,r1),r1
	mov	r2,r4
	mov	r1,r5
	mov.l	.L49,r1
	jsr/n	@r1
	mov	r14,r1
	add	#-4,r1
	mov.l	@(16,r1),r1
	tst	r1,r1
	bt	.L18
	mov	r14,r1
	add	#28,r1
	mov	r14,r2
	add	#28,r2
	fmov.d	@r2,dr2
	fabs	dr2
	fmov.d	dr2,@r1
.L18:
	mov	r14,r1
	add	#-4,r1
	mov	r14,r2
	add	#28,r2
	fmov.d	@r2,dr2
	ftrc	dr2,fpul
	sts	fpul,r2
	mov.l	r2,@(20,r1)
	mov.l	.L39,r2
	mov	r14,r1
	add	#-4,r1
	mov.l	@(20,r1),r1
	mov	r2,r4
	mov	r1,r5
	mov.l	.L49,r1
	jsr/n	@r1
	mov	r14,r1
	add	#-4,r1
	mov.l	@(20,r1),r3
	lds	r3,fpul
	float	fpul,dr2
	mov	r14,r1
	add	#36,r1
	mov	r14,r2
	add	#28,r2
	fmov.d	@r2,dr4
	fmov	dr4,dr6
	fsub	dr2,dr6
	fmov	dr6,dr2
	fmov.d	dr2,@r1
	mov	r14,r1
	add	#36,r1
	fmov.d	@r1,dr4
	mova	.L44,r0
	fmov.d	@r0,dr2
	fmul	dr4,dr2
	mov	r14,r1
	add	#-4,r1
	ftrc	dr2,fpul
	sts	fpul,r2
	mov.l	r2,@(24,r1)
	mov.l	.L42,r2
	mov	r14,r1
	add	#-4,r1
	mov.l	@(24,r1),r1
	mov	r2,r4
	mov	r1,r5
	mov.l	.L49,r1
	jsr/n	@r1
	mov	r14,r1
	add	#36,r1
	fmov.d	@r1,dr4
	mova	.L44,r0
	fmov.d	@r0,dr2
	fmul	dr2,dr4
	mov	r14,r1
	add	#-4,r1
	mov.l	@(24,r1),r2
	lds	r2,fpul
	float	fpul,dr2
	mov	r14,r1
	add	#44,r1
	fmov	dr4,dr6
	fsub	dr2,dr6
	fmov	dr6,dr2
	fmov.d	dr2,@r1
	mov	r14,r1
	add	#44,r1
	fmov.d	@r1,dr4
	mova	.L45,r0
	fmov.d	@r0+,dr2
	fmul	dr2,dr4
	fmov.d	@r0,dr2
	fadd	dr4,dr2
	mov	r14,r1
	add	#-4,r1
	ftrc	dr2,fpul
	sts	fpul,r2
	mov.l	r2,@(28,r1)
	mov.l	.L46,r2
	mov	r14,r1
	add	#-4,r1
	mov.l	@(28,r1),r1
	mov	r2,r4
	mov	r1,r5
	mov.l	.L49,r1
	jsr/n	@r1
	mov.l	.L48,r1
	mov	r1,r4
	mov.l	.L49,r1
	jsr/n	@r1
.L19:
	bra	.L19
	nop
.L50:
	.align 2
.L31:
	.long	1006960640
.L32:
	.long	.LC0
.L49:
	.long	_t_printf
.L34:
	.long	1079958831
.L35:
	.long	446676599
.L36:
	.long	___signbitd
.L37:
	.long	.LC1
.L39:
	.long	.LC2
.L44:
	.long	1086556160
	.long	0
.L42:
	.long	.LC3
.L45:
	.long	1083129856
	.long	0
	.long	1071644672
	.long	0
.L46:
	.long	.LC4
.L48:
	.long	.LC5
	.size	_main, .-_main
	.local	_buf.2581
	.comm	_buf.2581,100,4
	.ident	"GCC: (GNU) 4.4.0"

浮動小数点の演算に問題があることに気がついたのは、下記のコードで
double f1 が 負の値だったときに signbit() の戻り値が0だったからです。

コード:

	t_printf("Start of Code.\n");
	int sign;
	int d1, d2, d3;
	double f1, f2, f3;
	static char buf[100];
	f1 = -123.456;
	sign = signbit(f1);
	t_printf("sign = %d\n",sign);
	if(sign != 0) f1 = fabs(f1);
	d1 = f1;
	t_printf("d1 = %d\n",d1);
	f2 = f1 - d1;
	d2 = (int)(f2 * 10000);
	t_printf("d2 = %d\n",d2);
	f3 = f2 * 10000 - d2;
	d3 = (int)(f3 * 1000 + 0.5);
	t_printf("d3 = %d\n",d3);
	t_printf("\nEnd Of Code.\n");

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: sprintf関数の動作が変です

#20

投稿記事 by softya(ソフト屋) » 14年前

とりあえずFPUが呼び出し時は使われていますね。

コード:

    //	f1 = -123.456;
    mov r14,r3
    add #28,r3
    mov.l   .L34,r1
    mov.l   .L35,r2
    mov.l   r1,@r3
    mov.l   r2,@(4,r3)
    mov r14,r3
    add #52,r3
    mov r14,r1
    add #28,r1
    mov.l   @(4,r1),r2
    mov.l   @r1,r1
    mov.l   r1,@r3
    mov.l   r2,@(4,r3)
    //	sign = signbit(f1);
    mov r14,r1
    add #52,r1
    fmov.d  @r1,dr4 ← ここで浮動小数点レジスタのDR4に代入されています。
    mov.l   .L36,r1
    jsr/n   @r1
    mov r0,r1
    mov r1,r2
    mov r14,r1
    add #-4,r1
    mov.l   r2,@(16,r1)
signbit()関数がどうなっているかは分からないので、これで正しく動くかは謎ですが、FPUをコンパイラが認識している事は間違いないです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

およよ

Re: sprintf関数の動作が変です

#21

投稿記事 by およよ » 14年前

では、開発環境あるいはmakefileの設定に問題があるのかも知れません。
試しにGCCから再コンパイルしてみましょう。ベースとなるOSから
準備して何パターンか試すため、多少時間がかかります。

閉鎖

“C言語何でも質問掲示板” へ戻る