K.Maebashi's BBS

ご自由に書き込んでください。雑談も可。
テスト書き込みの類はテスト用掲示板にどうぞ

[日付順表示] [日付順インデックス] [スレッド順インデックス]


新規投稿 | 開設者ホームページへ戻る | ヘルプ


[2179] 汎整数拡張について
返信


投稿者:d_kuma
2019/08/05 17:43:35

Link:
お世話になっております。

汎整数拡張(又は整数拡張)について質問があります。

汎整数拡張という機能は、char型やshort型は、アセンブラ上ではint型と同じように扱われる、ということかなと思うのですが、この認識で合っているでしょうか?
Cのソースコードからアセンブラに変換されるときに、汎整数拡張によって何か変換処理が行われるわけではないと思っています。

試しに、char型、short型、int型による演算を、アセンブラ上で比較してみたのですが、差異が出てしまいました。
全て同じような結果になると期待していたのですが、そうはならなかったです。
あまりアセンブラに詳しいわけではないので、自信を持って言えるわけではありませんが。
[ この投稿を含むスレッドを表示] [ この投稿を削除]



[2180] Re:汎整数拡張について
返信


投稿者:(ぱ)こと管理人
2019/08/07 01:01:42

Link:
こんにちは。

>汎整数拡張という機能は、char型やshort型は、アセンブラ上ではint型と同じように
>扱われる、ということかなと思うのですが、この認識で合っているでしょうか?
>Cのソースコードからアセンブラに変換されるときに、汎整数拡張によって何か
>変換処理が行われるわけではないと思っています。

汎整数拡張という機能は、charやshortの変数でも、式の中ではintに変換される、
という機能です。変数に格納された値を使う時にはintでも、変数のサイズは、
charやshortならintより小さいわけですから、メモリから値を取り出して
(intと同じビット幅の)レジスタに乗せるときには汎整数拡張による変換処理が
入りますし、逆に(int型の)式の値をcharとかshortの変数に格納するときには、
逆の変換が必要です。

試してみました。

char_test.c
#include <stdio.h>

int char_test(void)
{
    char char_var = 5;

    printf("%d", char_var);
}

int_test.c
#include <stdio.h>

int int_test(void)
{
    int int_var = 5;

    printf("%d", int_var);
}

アセンブラ上の差異は以下です(Linuxでgcc -S)。

char_test.s
movb        $5, -1(%rbp)  ← char_var = 5のところ
movsbl        -1(%rbp), %eax ← char_varの値をeaxレジスタに移動

int_test.s
movl        $5, -4(%rbp) ←int_var = 5のところ
movl        -4(%rbp), %eax ← int_varの値をeaxレジスタに移動

int_test.sでは、単に32ビットを移動するmovl命令が使われていますが、
char_test.sでは、5をchar_varに代入する際にはバイトでの移動命令movbが、
char_varの値を取り出すときにはバイトを32ビットに変換しつつ移動する
movsblが使われていることがわかります。
[ この投稿を含むスレッドを表示] [ この投稿を削除]



[2181] Re:汎整数拡張について
返信


投稿者:d_kuma
2019/08/08 17:42:29

Link:
ご連絡遅くなりました。

アセンブラの解説をしていただき、ありがとうございます。
char型はアセンブラ上で変換が入るということで理解しました。
会社内で汎整数拡張について聞いてみたら、アセンブラ上で差異は無いと言われたので、間違って理解していました。
movsblというのが分からず、ネットで調べました。
movsはsign extension(符号拡張)によるコピー、blはfrom byte(8ビット) to long(32ビット)ということで理解しました。

これに付随して、さらに質問があります。
“得或拡張により、char型やshort型は、値を取り出す時に32ビットに変換されるので、int型より処理時間がかかったり、int型より実行ファイルが増大したりするのでしょうか?
汎整数拡張があるので、char型やshort型を使わずに、int型を使った方が良いのでしょうか?

,砲弔い討蓮char型やshort型を使うと、アセンブラ上で余計な変換が入って実行ファイルが増大してしまう、ということが書かれた技術書を読んだことがあります(『CプログラミングFAQ』だったと思います)。

△砲弔い討蓮C言語ではint型が基準なので、できるだけint型を使うべきなのかなと思っています。
巨大な配列を扱う時にメモリのサイズを減らしたいのでchar型やshort型を使うのはいいと思うのですが、
そうでないなら、できるだけint型を使うべきではと思っています。
[ この投稿を含むスレッドを表示] [ この投稿を削除]



[2182] Re:汎整数拡張について
返信


投稿者:(ぱ)こと管理人
2019/08/11 01:20:26

Link:
『CプログラミングFAQ』は、持ってたはずなのですが、どこを探しても見当たらない……

>“得或拡張により、char型やshort型は、値を取り出す時に32ビットに変換されるので、
>int型より処理時間がかかったり、int型より実行ファイルが増大したりするのでしょうか?

この手の性能問題は私は全然詳しくないのですが(アプリケーションプログラマですので…)、
今時のCPUを相手に、どちらが良いとか悪いとかそう一概に言えるものではないと思っています。
たとえば先のchar_test.sとint_test.sをそれぞれGAS(GNU assembler)にかけてみると、
movsblの命令長はmovlよりも確かに長いのですが、int int_var = 5; の「5」が
32ビット幅になるので、結局のところ実効形式のサイズとしてはint_test.sの方が
微増しているようです。

char_test.s
  17 0008 C645FF05              movb    $5, -1(%rbp)
  18 000c 0FBE45FF              movsbl  -1(%rbp), %eax
  19 0010 89C6                  movl    %eax, %esi

int_test.s
  17 0008 C745FC05              movl    $5, -4(%rbp)
  17      000000
  18 000f 8B45FC                movl    -4(%rbp), %eax
  19 0012 89C6                  movl    %eax, %esi

特に配列なら、主記憶は十分にあっても、今時キャッシュに乗らないと性能は出ないので、
小さな型を使った方が早いケースはあるかもしれません。
配列でないなら、どちらにしても、そう大差があるとは思えませんが。

>汎整数拡張があるので、char型やshort型を使わずに、int型を使った方が良いのでしょうか?

配列でないスカラの変数であれば、たとえば1バイト文字しか入らないとわかっていても、
私ならintを使います。「ポインタ完全制覇」にも書きましたが、getchar()の
戻り値やputchar()の引数も、実際intですし。
[ この投稿を含むスレッドを表示] [ この投稿を削除]



[2183] Re:汎整数拡張について
返信


投稿者:d_kuma
2019/08/12 21:46:36

Link:
お世話になっております。
細かい内容について答えていただき、ありがとうございます。

char,shortと、intでの処理速度やサイズの違いについて、よく分かりました。
現在の処理環境なら、あまり気にする必要は無いのかな、という気がしました。

スカラの変数ならintを使うということも理解できました。

お忙しいところ、ありがとうございました。
[ この投稿を含むスレッドを表示] [ この投稿を削除]