• ベストアンサー

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

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

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

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

> >・・・OSの役割を、・・・ > パソコンの基礎を学んでいない素人ですので、よろしくお願いします。 いや、逆ですよ。 やりたい事なために自分で学ばないといけないんです。 環境や人の性にしてはいけません。 そもそも、こんな所の基礎を教えてくれるところなんて情報工学系の大学くらいです。 ※ それでも情報工学系の大学生の多くの人は、優秀な人を除いてちゃんと理解できているか怪しいですが。 基礎をすっとばすから訳が分からなくなるんです。 言い訳じゃなく、自分でやるべき事(OSとCPU動作を基礎から勉強)をやってください。

7777777v
質問者

お礼

厳しいお言葉厳粛に受け止めさせて頂きます。 暇があればそうしたいのですが、あっと言う間もない人生の終りに近づくと焦ってしまい、かえって逆効果のようですね・・・ハイ。

その他の回答 (5)

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

前から思っていたけど仮想記憶メモリ空間とかOSの役割を、まったく理解していないじゃないかなぁ。

7777777v
質問者

お礼

>・・・OSの役割を、・・・ パソコンの基礎を学んでいない素人ですので、よろしくお願いします。

  • wormhole
  • ベストアンサー率28% (1621/5657)
回答No.4

>32bit用のレジスタの組み合わせで64bitのスコープを捕らえることはできないでしょうか? アドレス空間が32bitしかないモードで動いてるのなら、何をどうやってもそれを超える空間にはアクセスできません(そんな空間あること自体わからないんだし)

7777777v
質問者

お礼

回答ありがとうございます。 32bit環境で開発したアプリを64bit環境で動作させる場合を想定していましたが、他の方回答でよくわかりました。

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

Windows64bitOSで32bitアプリケーションが動く場合は、WoW64配下で動きます。 この場合は、4GB分の仮想メモリしか割り当てられませんので、32bitの外と言うメモリ自体が割り当てられていません。 なので、想定が変なのです。

7777777v
質問者

お礼

再度ありがとうございます。 専門的なことはわかりませんが、余計な事を考える必要はなかったようです。 ありがとうございました。

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

32bitのモードで動く場合は機械語命令もアドレスが32bit空間に制限されます。 つまり前提に問題有り。

7777777v
質問者

お礼

回答ありがとうございました。 >32bit空間に制限 32bitアプリケーションが動作する場合はOSが判断して割り当てる変数アドレスは32bit以内の空間になると判断していいでしょうか?

  • wormhole
  • ベストアンサー率28% (1621/5657)
回答No.1

32ビットしか扱えないコンパイラが64ビットに関するもの(命令やレジスタ)を理解できるとは思えませんが。 >セグメントレジスタとは何でしょうか? 調べればわかること。

7777777v
質問者

お礼

回答ありがとうございます。 >調べればわかること 検索しましたが、内容がわかりません。 32bit用のレジスタの組み合わせで64bitのスコープを捕らえることはできないでしょうか? 例えば __int64 II = offset *buf int i = II / 2; _asm mov esi,i _asm mov ebx,esi _asm mov eax,[esi+ebx] 変数割り当てのアラインで偶数番地となり、除算で端数はまずでないと思います。 この例で問題点があればご指摘ください。

関連するQ&A

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

    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が入って欲しいのですが無理なのでしょうか? 普通の感覚から考えてビックエンディアンが良いと思うのですが、 リトルエンディアンは何に便利なのでしょうか?

  • OSはどのようにして、CPUにメモリ上の物理アドレスを伝えるのか?

    一般的なシステムにおいて、プログラムを実行するには、コンパイラが再配置可能なオブジェクトファイルにして、そのオブジェクトファイルをローダがメモリ上にローディングして、CPUによって実行が行われると認識しています。 では、実際にCPUにより実行される時に、どのようにしてCPUは、ローディングされている物理アドレスを知ることが出来るのですか?一番初めにOSがどのようにCPUに先頭番地を伝えているのかが見当がつきません。例えば、486では、セグメントレジスタの値とオフセットアドレスを加算したアドレスを基にメモリとやり取りしていますが、OSがこのセグメントレジスタに先頭アドレスをどのように格納しているのかを教えてください。お願いします。

  • 関数の型

    C言語の勉強をしております。 以下のように、入力用の関数を作成し、入力された文字列を返して欲しいんですが、「1 番目の引数を 'char *[80]' から 'char *' に変換できません。」という警告メッセージが出てしまい、解決出来ません・・・。 原因と解決策を教えていただけないでしょうか? ちなみに環境はWindowsXP、コンパイラはVC6.0です。 #include <stdio.h> char *insertName(char *buf); int main(void) { char *buf[80]; buf = insertName(buf); printf(buf); return 1; } char *insertName(char *buf) { gets(buf); return buf; } mainの「buf」の定義を「char *buf」にすればエラーは出ないんですが、大きさを指定したいので・・・ どうかよろしくお願いいたします。

  • C++とインラインアセンブラでのポインタ値が違う

    C言語で取得した配列変数の先頭ポインターとインラインアセンブラで取得したポインターが異なる現象が起きました。 2個のソースファイルを持つ下記プログラムで、pointer1とpointer2が異なる原因を教えてください。 ただし、提示のソースはあくまで、見本で実際には多くの変数やコードを記述しています。 開発環境はWin7(64bit)、VC++2010無償版です。 main.cpp #include <windows.h> int *disp; int *pointer1; int *pointer2; int data[8]; void disp_sub(); int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) { _asm{ mov disp,offset disp_top call disp_sub jmp pgm_end disp_top: lea eax,data mov pointer1,eax } pointer2=&data[0]; if(pointer1 != pointer2)Beep(3000,1000); _asm ret pgm_end: return 0; } sub.cpp extern int *disp; void disp_sub() { _asm{ call disp } }

  • C/C++のインラインアセンブラに関する質問

    使っているコンパイラはボーランドのフリーのC++のコンパイラなのですが インラインアセンブラのソースをコンパイルするとこんなエラーメッセージがでます( 警告 W8002 roger.cpp:8アセンブラを使う為コンパイラを再起動した(関数(main()) エラーE2133 ’tamsm32.exe'を実行できない とエラーメッセージが出ます 調べても解決方法がわからないのですが 解る方は教えてください ついでにコンパイルしようとしたソースは↓です #include<iostream.h> void main(){ int w=8; int w2=5; _asm{ mov eax,w mov edx,w2 }; cout<<w<<endl; };

  • ビット幅とその出力について

    C言語を習い始めた者ですが、ビット幅とその出力についてわからないことが二つでてきました。以下のソースコードを見てください。 #include <stdio.h> int main(void) { char ss[] = "ABCDEF"; void *vpt; int idt; vpt = ss; idt = * (char *)vpt; printf("char:%x\n", idt); idt = *(int *)vpt; printf("char:%x\n", idt); return 0; } 出力結果は char:41 char:44434241 となります。 一つ目のわからないことは char:41 についてです。私はchar型のビット幅は8ビットで文字ABの16進数を出力すると予想していました。ところが結果は 文字A の16進数の41のみが出力されました。Aの二進数は 1010、 Bの二進数は1011で それぞれ4ビットずつ持っていて合わせて8ビットになるのでそう考えていました。よくわかりませんが結果から、文字一文字に対して8ビットつまり1バイトに相当するのでしょうか? 二つ目は char:44434241 についてです。一つ目の質問に書いた推測が正しければ1文字を1バイトと考えて16進数にすると Aは41 Bは42 Cは43 Dは44 になります。しかしポインタの先頭のアドレスはAになっているはずなのになぜか出力は char:41424344 ではなくchar:44434241になっています。順序が逆になっているのでしょうか? Cをはじめたばかりなので基本的なところがわかっていないかもしれませんが、説明に不足があればつけたしますのでどうかよろしくお願いします。 

  • DTCのレジスタ情報設定方法についてご教示ください。

    DTCのレジスタ情報設定方法についてご教示ください。 はじめまして。 現在、SH7145マイコンを使って、DTC、SCIを使用したシリアル通信を 考えておりますが、以下の点で困っております。 転送情報を設定するために、 DTBRに転送情報の先頭アドレス上位16ビット、 DTCベクタアドレス(TXI_0 0x0000043A)に先頭アドレスの下位16ビット を設定しているのですが、0x0000043A番地にアドレスが設定されません。 HEWのデバッガを使用しており、0x0000043A番地を見るとFF FFのままです。 デバッガで0x0000043A番地に、直接下位16ビットの値を設定し、 0x0000043A番地を読みに行った場合には、設定した値を取得出来ました。 そこでプログラム中で正しくアドレスを設定する方法についてご教示ください。 また、DTCベクタアドレス(0x00000400番地から)はROMエリアになる事により、 HEWのビルドの設定等で対応することになるのでしょうか? 以上、よろしくお願いいたします。

  • VC2005(x86系)の実行アドレス取得方法について

    VC2005(x86系)において、現在実行中のRAMアドレス(プログラムカウンタ) を取得したいのですが、どのようにすれば良いでしょうか。 【やってみたこと】 下記のようにすれば出来るかと思ったのですが、 コンパイルエラーでした...。 (eipが使えないとのこと) -------- void main() { unsigned long pc_pos; __asm { mov pc_pos, eip } ・ ・ ・ } -------- 特にアセンブリでやりたいとかの指定はございません。 ただ、実行しているプログラムカウンタ位置を取得する 方法がございましたら、ご教授願えませんでしょうか。

  • 配列変数のポインターが勝手に変わる

    下記の2個のファイルを持つプログラムでインラインアセンブラのcall命令で配列変数のポインター(アドレス)が勝手に変わる現象をおしえてください。 但し、配列の最初のポインターのみが変わる。 開発環境はWin7(64bit)、VC++2010無償版です。 main.cpp int *disp; int data[3]; WinMain() { _asm mov disp,offset disp_top ・ ・ ・ メッセージループへ _asm{ disp_top://下記move()からcallされた時 lea eax,data//下記のmove()関数のeaxの値より16番地少ない lea ebx,data+4//下記のmove()関数のebxの値と同じ lea ecx,data+8//下記のmove()関数のecxの値と同じ ・ ・ ・ ret   } } move.cpp extern int *disp; extern int data[3]; void move() { _asm{ lea eax,data lea ebx,data+4 lea ecx,data+8 call disp   } }

  • I/Oレジスタアドレスを関数に引数として渡すには?

    C言語について質問があるので投稿させていただきました。 現在Renesas製 RXマイコンにてポート制御のプログラムを作成しています。 そこで一点分らない点がありましたのでご教授いただければ幸いです。 現在I/Oポートレジスタの入出力設定を行っています。 レジスタ値を書き換えるだけであれば下記の通りかと思います。 #define PORTA (*(volatile unsigned char *)0x0008C00A) PORTA = 0x01; レジスタアドレスを引数として関数に渡し関数内でレジスタ値を書き換えるにはどうすれば よろしいでしょうか。 void main(void) { setPinMode(PORTA); PORTA.PODR.BIT.B0 = 0x01; while(1); } void setPinMode(uint32_t* portNumber) { *portNumber = 0x01; } としていますが上手くいきません。 型がおかしい? ポインタってものが分かってない? など色々考えてはみたのですが何分初心者なので解決に至っておりません。 よろしければご教授の程よろしくお願いいたします。

専門家に質問してみよう