• ベストアンサー

リトルエンディアンというものでしょうか?使いづらいです。

VC6で以下のようにメモリ上の4バイトは逆さなのでしょうか? 非常に使いづらいです。 正しく?1を取得する方法が知りたいです。 int a[2] = { 1, 2 }; _asm{ // 2003年頃の本を見ると__asmだし、他ではasmだった。 _asmはVC特有? mov esi, a // メモリ上では 0x01 0x00 0x00 0x00 0x02 0x00 0x00 0x00と逆さに入ってる mov eax, [esi+0]; // eaxが 0x10000000 // eaxには1が入って欲しいのですが無理なのでしょうか? 普通の感覚から考えてビックエンディアンが良いと思うのですが、 リトルエンディアンは何に便利なのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.7

やりたいことを Cで記述しその部分にブレークポインタを設定、実行します ブレークしたら 表示 > デバッグウィンドウ > 混合モード で アセンブラコードとソースが一度に参照できます コンパイラがどのようなコードを吐いているの確認してみましょう ポインタなら その中身は何処かのアドレスを挿しています 引数の配列なら Cではポインタで渡されます mov命令でレジスタに設定できます リスティングファイルでアセンブラファイルを作ってしまうなんて方法もあります プロジェクト > 設定 > C++タブ > カテゴリ-> リスティングファイル で設定できます

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (6)

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.6

#3のzwiです。 >x自体がポインタだからと思います。 >そう理解してよいでしょうか? そうです。 mov esiは、メモリから値(この場合はポインタ値)をesiレジスタにロードする命令です。 lea esiは、アドレスを計算してesiレジスタにロードする命令です。 ポインタの場合は上記を、変数を直接参照する場合は下記の命令を使います。 ここで例を挙げてみます。 int a[2]; と書かれていた場合と int b[2]; int *a = b; と書かれた場合ですが、C言語での値の取り出しはどちらもa[0]で取り出せますよね。 しかしアセンブラでは違いを意識しないといけません。 a変数からアクセスをする場合、上記はlea、下記はmovを使うことになります。

全文を見る
すると、全ての回答が全文表示されます。
  • yphkz4063
  • ベストアンサー率23% (34/144)
回答No.5

ビッグとリトルが逆に見えるというのは人の都合でしかありません。 ハードから見れば同じに見えます。 そう思えばたいした問題ではありません。 失礼ながら、質問内容がバグっているような気もしますが・・・。

tobasu
質問者

お礼

現場の方、コメントありがとうございます。 目から鱗でした。 >失礼ながら、質問内容がバグっているような気もしますが・・・。 いつも半分、そうです。(^^;

全文を見る
すると、全ての回答が全文表示されます。
  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.4

リトルエンディアン:ビッグエンディアンよりすぐれた方式。 ビッグエンディアン:リトルエンディアンよりすぐれた方式。

tobasu
質問者

お礼

回答ありがとうございます。 直ぐに理解できませんでした。 今度から平易な内容でお願いいたします。

全文を見る
すると、全ての回答が全文表示されます。
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.3

リトルエンディアンのメリットですか? そもそもは設計思想の違いとしか言いようが無いですね。 リトルエンディアンは、小さい桁の数値を小さいアドレスから書くべきだという考え方で設計されています。これはソフト的な思想ではなくハード設計者の思想です。 一度そういう思想で設計しちゃったら同じ会社でCPUを作る限り続けるしかないわけです。前のCPUで作ったデータの読み書きで困りますからね。インテルだと初期の8ビットCPUの8008がそういう設計思想でした。そこから今の64ビットCPUまで延々と続いているんです。 特徴としては、元の格納データサイズを知らずにデータを取り出せることでしょうか? 例えば、0x12345678という値はメモリ上では、 0x78 0x56 0x34 0x12 と格納されています。 下位1バイトを取り出すと、0x78と言う下位データが取り出せます。 下位2バイトを取り出すと、0x5678と言う下位2バイトのデータが取り出せます。 これはビックエンディアンでは、元々の格納長を知らなければ取り出せません。4バイトと知っていて始めて取り出せるのです。 何に使えるか?って聞かれると困るんですけどね(^^ゞ

tobasu
質問者

お礼

為になります。

全文を見る
すると、全ての回答が全文表示されます。
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

インテル系x86 CPUでしたら esiが配列 aを取得できているのであれば mov eax,[esi+0]; で eaxは 1が格納されます ただ mov命令で esiに 配列aの先頭アドレスを取得できません やるなら leaなどのLoad系の命令を使います lea esi, a; といった具合です

tobasu
質問者

お礼

>ただ mov命令で esiに 配列aの先頭アドレスを取得できません >やるなら leaなどのLoad系の命令を使います 大域変数の場合、 lea esi, a でうまくいきました。 関数で配列のポインタを使う場合 void test(const int x[]) の場合は、 mov esi, x でないと、うまくいきません。 x自体がポインタだからと思います。 そう理解してよいでしょうか? 最初の1が取得できない件は、指すアドレスが間違っていて、たまたま指しているデータが0x1000000でした。すみませんでした。

全文を見る
すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

ん? eax って 0x10000000 になりますか? 1 になるような気がするんだけど....

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • リトルエンディアン、ビッグエンディアンについて

    リトルエンディアン、ビッグエンディアンについて 質問があります。 (1)簡単にそのPCがリトルエンディアンなのか、ビッグエンディアン  なのか、分かる方法はありますか?  簡単なCプログラムを書いてメモリ状態をダンプするのが、  一番早いのでしょうか?  それとも、Intel系?モントローラ系?CPUにはあまり詳しくないので、  分かりませんが、これらのどちらかに属していれば決められるので  しょうか?ほかの系とかあるのかな・・・ (2)ネットワークプログラミングをするときに、ビッグエンディアンの  マシンからデータを送出する場合には、htonlなどの関数を使用しなく  ても問題ありませんでしょうか?(ネットワークバイトオーダが  ビックエンディアンであるため)

  • リトルエンディアン→ビッグエンディアン

    (1)リトルエンディアン typedef struct recvData{  int a;  unsigned char b[16]; unsigned char c[8]; unsigned int d[4]; } recvData_t; recvData_t rData; (2)ビッグエンディアン typedef struct sendData{  int a;  unsigned int b[4]; unsigned int c[2]; unsigned int d[4]; } sendData_t; sendData_t sData; 上記のようなリトルエンディアンの構造体の各メンバのデータを、ビッグエンディアンの構造体の各メンバのデータにそれぞれ格納するには どうしたらよいでしょうか?

  • 最近のCPUのほとんどはリトルエンディアンかビッグエンディアンでしょうか?

    2000年あたり以降に出た Windows, Mac, Linuxに使われているCPUのほとんどはリトルエンディアンかビッグエンディアンでしょうか? また、たとえば以下のような方法でエンディアンを調べられると考えていいのでしょうか?(VC++です) #include <windows.h> void GetEndian4(char* c){ unsigned __int32 a=0x03020100; BYTE *b = (BYTE*)&a, i=4; while (i--) c[i]=b[i]; } ////////// const char e[4]={}; GetEndian4( const_cast<char*>(e) ); //eが 0,1,2,3 になればリトルエンディアン //3,2,1,0 になればビッグエンディアン //PDP-エンディアンだと 2,3,0,1 …のはず (または2択ならこれだけでも判断可能…?) short s=1; printf( *(char*)&s ? "リトルエディアン\n" : "ビッグエディアン\n" ); あとここでもアラインメントの問題が絡みますが、このように アラインメントが(2のべき乗だとして)大きいであろう方から小さいであろう方にキャストする分には安全で、逆に sizeof(short) == sizeof(char)*2 として char c[2]={1,0}; short s=*(short*)&c; というのは危険な場合がある、ということでしょうか? また、その場合は たとえばビッグエンディアンなら short s=(c[0]<<8)|c[1]; とすればいいでしょうか?

  • エンディアンについて

    すみません。 教えてください。 リトルエンディアンからビッグエンディアンに変換しないと いけません。 エンディアンについては勉強したつもりですが、 どうしてもわからないことがあります。 ご存知の方、教えていただせんか? CPUはリトルです。 まず、エンディアンの違いについては 以下のように認識しています。 x = 0xAABBCCDD メモリの配置方法が、 トリルだと DD CC BB AA ビックだと AA BB CC DD だと思っています。32ビットの場合です。 で、これを変換するには、htonlで変換可能だと思っっています。 (試したところ可能でした) で次に、32ビットを超えるデータ、たとえば100バイトとかを mallocにして変数に代入しました。 この時はエンディアン変換(ファイルに出力する際)は必要ないのでしょうか? 試しに出力すると、 x = 0x AA BB CC DD EE FF GG ・・・・・・ZZ (100バイトと仮定) バイナリでの出力結果は AA BB CC DD EE FF GG ・・・・・となっていました。 私の認識だと、本CPUはリトルエンディアンのため、 ZZ ・・・・・・・・ DD CC BB AA (四バイトずつ反転しているデータ) が出力されるものと思っていました。(反転してメモリに格納されるため) リトル/ビックを意識しないといけないのは、 2バイトや4バイトの時のみで、それを超える大きなデータ(100バイト)などは 意識せず、そのままバイナリ出力しても、ビックエンディアンで出力されると いうことでよろしいでしょうか? そうなると、エンディアンってなんだんだ???と混乱しています。 わかりにくい説明で大変申し訳ござませんが、 よろしくお願いいたします。

  • ビッグ/リトルエンディアンについて

    現在、ワークステーション(SPARC+Soralis)上でFortranで書かれたプログラムがあります。 それをPC(x86+WindowsXP)の環境へ移行した所、Fortran記録(バイナリ)の内容が、CPUアーキテクチャの絡みでビックエンディアン/リトルエンディアンの問題が発生し、苦労しています。 Windows側で使用しているFortranコンパイラは「富士通 Fortran&C Packege V4.0」です。 PC側でまともにワークステーションのバイナリファイルを読みたいのです。 どなたか対策をご存じの方がいらっしゃいましたら、ぜひ、ご教授ください。 よろしくお願いいたします。

  • エンディアン反転まわりの速度関係

    エンディアンの反転を高速でやる方法を模索していたのですが コンパイラはVC++2008EE OSがWindowsXP SP2 32 bitで 最適化オプションなしでやれば DWORD d=242397; __asm { mov eax, d bswap eax mov d, eax } のほうが DWORD d=242397; d=_byteswap_ulong(d); よりも4倍程度速かったのですが 実行速度 (/O2) または 最大限の最適化 (/Ox) の最適化オプションだと 後者の方が前者より3倍ほど速く実行されました。 そこでbswapではなくビットシフトを使ったら d = ((d & 0xff000000) >> 24) | ((d & 0x00ff0000) >> 8 ) | ((d & 0x0000ff00) << 8 ) | ((d & 0x000000ff) << 24); これでほぼ同じ速度になりました。 これらの速度関係は、Windowsでは比較的安定しているのでしょうか? それともWindowsでもまちまちなのでしょうか?

  • JAVAのdouble型情報をリトルエンディアンでバイナリへ出力の方法

    JAVAでdouble型の情報をリトルエンディアンでバイナリとして出力する方法を教えてください。 現在、java.io.DataOutputStreamを使用し、writeDoubleで出力していますが、ビックエンディアンとしてしか無理でした。 読み込むのはテキスト型で出力がバイナリ。 現在のソースの簡易フローチャートを書いて置きます。 START ↓ テキストファイルから特定の文字列を取得する(1 , 7 , 5.5等) ↓ 取得した文字列をそれぞれ対応の型に変換する int top = Integer.parseInt("1"); int sub = Integer.parseInt("7"); double miks = Double.parseDouble("5.5"); ↓ バイナリのフォーマットに合わせて出力する int型は4バイトでビックエンディアン。 double型は8バイトでリトルエンディアン。 例えば、デフォルトのビックエンディアンで出力した時、数字の1は 00 00 00 01 になりますが、 リトルエンディアンで出力した時は、 01 00 00 00 になると思います。 変換するタイミングとしては、書き込む時にオリジナル機能(メソッド)で書き込むデータ(int型やdouble型)とビックかリトルを指定して、バイナリに出来るものを探しています。 PS 現在の質問はソースを上げるのが一番とは思いますが、社外秘のソースなので、公開することは出来ません。 PPS 私の質問に対する質問があれば、より詳細に答えていくつもりです。 以上、宜しいお願い致します。

    • ベストアンサー
    • Java
  • LITTLE_ENDIAN変換の結果の16進表示

    毎度、お世話になります。 下記のコードで、 bsはLITTLE_ENDIAN変換を行い、十進数表示で、67305985と表示されます。 これを、0x04030201とprint_outするコードをお教えください (1度intに変換しまして、そのintの内容を16進表示としたいと思います)。 byte[] bs = {0x01,0x2, 0x3, 0x4};  //lsd...Msd 0x04030201 ByteBuffer buffer = ByteBuffer.wrap(bs); buffer.order(ByteOrder.LITTLE_ENDIAN); System.out.println(buffer.getInt()); 以上、宜しくお願いします。

    • ベストアンサー
    • Java
  • リトルエンディアンの1byteデータのビット割付

    リトルエンディアン方式と聞くと2byteデータだったら上位下位が逆転して メモリに割りついているって認識なんですけども、ビット割付も逆転している認識 で問題ないでしょうか? 例えば、1byteの0x1Fというデータがリトルエンディアン方式のビット割付だった場合 1111 0001という割付になるのでしょうか?

  • 32ビットレジスタで64ビット空間をアクセスする

    char *buf; _asm mov esi,buf _asm mov [esi],0x77 bufの先頭アドレスが32ビットを超える位置にある場合に 32ビットしか扱わないコンパイラで可能にする記述を教えてください。 セグメントレジスタとは何でしょうか? VC++でインラインアセンブラで記述します、よろしくお願いします。