q_and_aの過去ログ(0006)

  • (by K, 2007.01.29)

ログ

  • 第1版の第2刷のp.193のstruct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;の構造体の値設定がわかりません。具体的にはmemman.freesなどの変数にはどのような値が代入されるのですか。 -- fio 2006-09-07 (木) 10:09:04
  • 初版第四刷のp.38からの質問です。MOV AL , BYTE [SI]をビット数が同じもの同士でしか代入できない規則があってALに代入する以上、BYTE以外はありえないという理由から MOV AL , [SI]と省略して書いてあります。そして駄目な例としてMOV AX , CLを挙げていますが、CLから代入される以上やっぱりBYTE以外ありえない(8ビットレジスタだから)ような気がするのですが、なぜ省略できないのでしょうか? MOV AX , [CL]なら省略できない理由は分かりますが。 -- 名無しさん 2006-09-08 (金) 03:01:55
  • fioさんへ。memmanの値は0x3c0000になるので、「memman->freesの値」は「メモリの0x3c0000番地に書かれている値」になります。これがいくつなのかはこの段階では分かりません(たぶんでたらめな値が入っている)。その後の memman_init(memman); の実行で、memman->freesは確実に0になります。 -- K 2006-09-08 (金) 09:34:53
  • 名無しさんへ。p.38をもう一度よく読んでもらいたいのですが、 MOV AX,CL は「BYTEを省略できない」のではなく、「そもそもそんな命令は存在しない」のです。なぜなら、AXは16ビットレジスタでCLは8ビットレジスタですから、この命令は「ビット数が同じもの同士でしか代入できない規則」に反しているのです。したがって MOV WORD AX,BYTE CL と書き足しても、エラーはなくなりません。当たり前ですが、 MOV AX,CX や MOV AL,CL であれば、何の問題もなく機械語に翻訳されます。 -- K 2006-09-08 (金) 09:39:50
  • ちなみに MOV AX,[CL] に関して言えば、[CL]という指定そのものがエラーになるのでうまくないのですが(番地指定に使えるのは、本文にあるとおりBX、BP、SI、DIだけ)、 MOV AX,WORD [BX] のWORDは省略可能です。つまり MOV AX,[BX] はエラーではありません。AXは16ビットレジスタですから、WORD以外はありえないと判断できるためです。 -- K 2006-09-08 (金) 09:48:27
  • とても丁寧なお返事有り難うございます。分かりました! -- 名無しさん 2006-09-08 (金) 11:18:53
  • Kさん。迅速でそしてわかりやすい回答woありがとうございました。 -- fio 2006-09-08 (金) 15:26:04
  • 初版第四刷p84からp85までの質問です。変な質問ですいません。いきなりharib01fで難易度があがったのでビビっているのですが、staticっていうのは「RESB命令の代わりにDB命令を使うように指示する」と書いてありますが、RESB命令で48バイト分予約して、そこにDB命令で0x00から順に書いていくみたいな理解で大丈夫ですよね。それと、関数set_paletteはvoid set_palette(int start, int end, unsigned char *rgb)と宣言してありますが、最後のunsigned char *rgbというのはtable_rgbを省略?して書いた物ですよね?この前にポインタをいっぱい勉強しましたけれど、この場合書き方が違うからポインタじゃないですよね? -- hatena 2006-09-09 (土) 08:46:29
  • hatenaさんへ。staticの件に関してはfaq/c04-07に書きましたので見てください。staticがある場合はRESB命令は出てきません(両方使うのなら「代わりに」なんていいませんよ)。関数set_paletteについてですが、パレットを設定するためには設定値のデータが必要です。そのデータがメモリのどこに並んでいるのかをこの関数に教えてあげなければいけません。それで、番地を教えてあげることにしました(この番地を直接知っているのは関数init_paletteだけです)。そのrgbという変数は関数init_paletteに教えてもらった番地を記憶しておくための変数です。つまりrgbという変数は「番地変数」なのです。だからこれもポインタです。 -- K 2006-09-09 (土) 12:07:20
  • 丁寧なお返事有り難うございます。どうしても理解できなかったので、「やさしいC」という本を今日買って来て読んでやっと分かりました。関数set_paletteの仮引数は番地変数rgbとしているんですね。そして、関数init_paletteからtable_rgbのメモリ番地の先頭が渡されて、番地変数rgbが初期化されるわけですね。そして、キャストの警告が出ないのは渡される値が最初からメモリ番地だからですね。C言語の本買ってきたのでしばらくこのまま進めそうです。重ね重ね有り難うございました。 -- 名無しさん 2006-09-10 (日) 01:19:21
  • 初版第2刷のP55で「MOV DL,0x00 ; Aドライブ」が2回出てくるのが気になります。DLを他に使ってなさそうですし、「readloop:」の前に持ってきても、同じように動作しているように見えますが、本のようにしているのはなぜでしょうか? -- mamezo 2006-09-10 (日) 17:49:03
  • 初版7刷からの質問です。(←あまり関係ありませんが…。) -- 名無しさん 2006-09-10 (日) 17:53:44
  • すいません↑は、間違いです。 -- 名無しさん 2006-09-10 (日) 17:54:10
  • 質問 質問 初版7刷からの質問です。(←あまり関係ありませんが…。) 一日目、17pの三行目に、(以下本文転載)そのディスクからpcを起動すると、(以上本文転載)と言うのがありますが、それはどのようにして起動する事なのかが分からないのです。分かる方がいらっしゃいましたら、ご回答お願いいたします。 -- ↑でミスをした、 キジっとヤッピィ 2006-09-10 (日) 18:01:00
  • キジっとヤッピィさんへ。それは、書き込んだFDをPC本体に差し込み、そしてPCの電源を入れ直す(再起動)と出来ます。 -- uchan 2006-09-10 (日) 19:44:22
  • ありがとうございます。 -- キジっとヤッピィ 2006-09-11 (月) 12:45:13
  • 初版第四刷p91とp92から質問です。io_out8関数でDXとALに数値を代入してout命令をしていますが、このOUTされたデータは最終的にどこに行きつきくのでしょうか?BIOSが使えたときは、レジスタに値を代入してしてBIOSの関数を呼び出していましたが、32ビットモードでの装置の使い方がいまいち分かりません。それともう一つは変な質問なのですが、io_load_eflagsの説明で「C言語の規約では、RETした時にEAXに入っていた値が関数の戻り値と見なされる」とありますが、なぜC言語を作った人はEAXに入っていた値を戻り値としたんでしょうか?アセンブラで自由に使えるEAXの値を戻り値にすると、例えばRETする直前にEAXに適当な値を代入すれば、戻り値を自由にいじれますよね?なぜ、EAX、ECX、EDX以外のC言語にとって大事な値を記憶させるレジスタにしなかったんでしょうか? -- hatena 2006-09-12 (火) 02:22:58
  • すいません。変な質問の方は愚問でした。忘れて下さい。 -- hatena 2006-09-12 (火) 04:00:06
  • 初版第四刷p97構造体からの質問です。xsize = (*binfo).scrnxでxsizeに320が代入されるわけですが、どのような過程でscrnxに320が代入されるのでしょうか?私のイメージでは0x0ff4に320が入っていて、binfoに0x0ff0をセットしてやることで、5番目の変数scrnxと番地0x0ff4と320が対応すると思っていました。しかし、自分の買った本では「構造体のサイズは各メンバのサイズを足し合わせたものかそれ以上になる」と書いてありました。もしそれ以上になるなら、メモリの番地と変数が対応しない事態が発生するような気がするのですが、コレは本が間違っているのでしょうか? -- 名無しさん 2006-09-13 (水) 12:44:15
  • ↑の名無しさんへ。前半部分の認識についても、買った本についても間違っていないと思います。ただ、5番目の変数だから、ではなく、自分より前の変数が全部char型(=1Byte)なので、scrnxのアドレスはxsizeのアドレス+4になると解釈した方が良いと思います。(つづく) -- 名無しさん 2006-09-13 (水) 16:11:11
  • (つづき)。で、本の話ですが、それは恐らくアライメントやパディングのことです。例えば、short型は2Byteですし、ポインタは4Byteです。こうゆう型は、それぞれ、2の倍数や4の倍数のアドレスに置いた方が処理が早くなります。なので、コンパイラが自動的に隙間を空けてメンバを配置する場合があるのです。当然、この場合は「構造体のサイズ=メンバの合計サイズ+隙間のサイズ」になります。scrnxについては、もともとが構造体の先頭から4の倍数の場所になっているので、隙間は入らず、先に書いたコメントのようになります。 -- 名無しさん 2006-09-13 (水) 16:18:25
  • 私自身が本を斜め読みしただけなので、はりぼて用のコンパイラに詳しくありません。何か気づいた点がありましたら、どなたか補足をお願いします。 -- 上二つ書いた人 2006-09-13 (水) 16:20:51
  • hatenaさんへ。質問の解答については、P.88の上半分に書いてあります。もう一度よく読んでみて、わからない点を絞って質問すると良いと思います。 -- 名無しさん 2006-09-13 (水) 16:57:39
  • 上二つ書いた人様、アライメントやパディングの事分かりました。今回はアセンブラの段階でアライメントやパディングが起きないようにデータをメモリに代入して、それに合わせて構造体を宣言したわけですね。名無しさんへ。どうもです、自分で調べて疑問が解けました。今度からもう少し考えて質問するようにします。 -- 名無しさん 2006-09-14 (木) 02:47:31
  • mamezoさんへ。そこは言うまでもなくエラーが起きたときに実行される処理なのですが、エラー時にDLの値がBIOSによって変更されずに済むかどうか自信が持てなかったので、そのように書きました。少なくともmamezoさんの使っているPCのBIOSでは大丈夫だったようですね。 -- K 2006-09-14 (木) 18:56:04
  • Kさん、お忙しいところ、ご回答ありがとうございます。エラー処理は丁寧に!ですね。大変勉強になりました。 -- mamezo 2006-09-14 (木) 20:47:41
  • 初版第四刷p116からの質問です。リミット(セグメントのバイト数-1のこと)と言う説明があって、その後実際にセグメント番号2を設定しているのですが、サイズが512KBになっています。これはセグメント番号2番は513KBのセグメントを作ろうとしたから、512KBにしたんですよね?それと、セグメント番号0はせっかく初期化したのに、使っていませんがこれは理由があるのでしょうか? -- 名無しさん 2006-09-18 (月) 14:45:02
  • Windowsの関数電卓などで確認してほしいのですが(30日目の電卓アプリでも可)、512KBというのは524288バイトです(512x1024)。これを16進数で書けば0x80000になります。そこでプログラムではここから1を引いた値、すなわち0x7ffffを指定しています。つまりセグメント番号2番はサイズが512KBのセグメントです。リミットはサイズから1を引いた値なので、0x7ffffを指定しているというわけです(サイズはリミットではないことに気をつけてください)。セグメント番号0番については、ご指摘のとおりせっかく初期化したのに使っていません。実はセグメント番号0番はGDT内に設定できるけど、実際には使ってはいけないセグメント番号なのです。それで使っていません。だからまあ実は設定する必要だってないのですが、これだけ初期化しないままにしておくのもかわいそうな気がしたので、初期化はしているというわけです(p.173のヌルセレクタの説明も参照のこと)。 -- K 2006-09-18 (月) 19:58:16
  • kさま、お忙しいところ丁寧なお返事有り難うございます。ご自愛下さい。 -- 名無しさん 2006-09-18 (月) 22:50:45
  • 初版第四刷p125からの質問です。くだらない質問なのですが、「arをあえて16ビットとして、xxxx0000xxxxxxxxと言うビット構成で使っています。」とありますが、arはint型で宣言されています。わざわざ16bitにしたなら、short型にした方がメモリが節約できて良いような気がするのですが、どうしてint型なのでしょうか? -- 名無しさん 2006-09-19 (火) 16:24:05
  • arの質問への回答:もしかしたら違うかもしれませんが、こうだと思うことを書きます。P70に有るように、C言語の関数の引数は、先頭から順にESP+4,ESP+8,...というようになっています。だから、引数がchar型だろうがshort型だろうがint型だろうか、4バイト以下の大きさなら結局同じだけメモリを消費すると思うのです。(合ってるかな?) -- uchan 2006-09-19 (火) 17:28:31
  • メモリ節約という観点で言うと、関数の引数はスタックに収まるので、関数がreturnしたらもうメモリが解放(SPが元に戻る)されて、メモリ消費は無かったことになると思います。 -- uchan 2006-09-19 (火) 17:31:44
  • uchan様、回答有り難うございます。つまり、「short型でも良いけれど別に結果は代わらないから、他の変数がint型だから、合わせてint型にしてみました。」と言う理解で良いのですね。それと、スタックって言うのはp91で出てきたものと同じスタックですね。アセンブラでしか使えないと思っていました。C言語のメモリの使われ方、勉強になりました。SPって言うのはスタックポインタのことであっていますよね。 -- 名無しさん 2006-09-20 (水) 02:51:39
  • そうですね。SPはスタックポインタです。 -- uchan 2006-09-20 (水) 21:59:33
  • 初版第6刷のP214,215のharib08aとharib08bについての質問なのですが、haribo08aのプログラムはマウスの座標(mx,my)の値によっては320*200の画面モードで利用できるVRAMの領域を越えてアクセスすることになると思うのですが、例えばmxはとりあえず適当な値としてmy=199のときにsheet_slideを読んだ場合など、これはまずくないのでしょうか?この事について本書では特に触れていないのですが,harib08 -- 名無しさん 2006-09-24 (日) 23:28:16
  • すいません書き途中でコメントの挿入しちゃいました。このまま続きを書かせて下さい。harib08bで対応するのでとりあえずVRAMの領域を越えたアクセスには触れず、さらっと読み流す程度でよいのでしょうか?それともVRAMの領域を越えたアクセスなんて起こってないのでしょうか?かなり長くなるのですがもうひとつ質問させて下さい。harib08bでvx0とvy0が0より小さくなるようなときの条件を調べているのですが、マウスの座標(mx,my)は共に0より小さくなることなんて無いようにしているはずなので必要ないのではと思うのですが?それとも現状では必要ないが、後で何かしら必要となるのでとりあえず入れておいたということで宜しいのでしょうか?  本来ならこのような細かい所はさらっと読み流すべきなのかも知れないのですが、私自身細かいことが気になると先に進めなくなってしまう性分なので、このような長く変な質問になってしまってすいませんでした。 -- 名無しさん改めast 2006-09-24 (日) 23:46:21
  • astさんへ。的確な質問をありがとうございます。harib08aについてですが、ご指摘のとおりおかしくなるかもしれません。もし度胸があれば是非my=199になるようにマウスを下に動かしてみてどうなるかに挑戦してみてください(怖ければやらなくてもいいです、もちろん)。実機ではなくエミュレータ上でやると少しは安全度が増していいかもしれませんが、こういう微妙な動作はエミュレータでは正しくエミュレーションできていないかもしれません。・・・挑戦した結果にどうしても納得がいかない場合はまた質問してください。 -- K 2006-09-26 (火) 01:17:37
  • harib08bについての質問で、とりあえずmxやmyが負になることはないじゃないかという指摘もまことにもっともなのですが、下じき制御に関する関数群は、p.198にあるように、将来はマウスの重ね合わせ処理に限定せずにウィンドウの重ね合わせにも使えるようなものを考えています。そういうことを考えると、ウィンドウが画面外上方に出てしまうこともありえるだろうと思ったのです。ということで、まさに「それとも現状では必要ないが、後で何かしら必要となるのでとりあえず入れておいた」というわけです。 -- K 2006-09-26 (火) 01:26:37
  • ただこれはどちらの質問にも言えることですが、「こうなったらどうなるのか?」「これは必要なのか?」と思ったら、(それなりに注意を払って)とにかくやってみたり、不要と思われる部分を削除してどうなるかを観察してみたりを、まずはやってほしいです。そういうことをしていたら、また質問も変わってくるでしょう。 -- K 2006-09-26 (火) 01:29:49
  • 9/19の名無しさんへ。スタックに関してはuchanさんの説明のとおりですが、実はarの部分をshortにしてmakeすると、出来上がるharibote.sysの大きさが増えます(運よく変わらないこともあるかもしれません)。とりあえずharib03cでやってみたところ、intからshortに変更したらサイズが4バイト違いました。これは32bitモード時にはshortでの処理よりもintでの処理のほうが短い機械語で書けるためです(ちなみに32bitモード時では、shortよりもintのほうがわずかですが処理時間も短いです)。それでintにしました。 -- K 2006-09-26 (火) 01:45:29
  • Kさんへ、質問へのご回答ありがとうございました。harib08aやharib08bに関しては事前にエミュレータ上でmy=199にしてみたり(実機の方ではharib00iから動かないので未検証)、vx<0,vy<0の該当箇所をコメントアウトして動かしてみたりして、特に目立った変化がなかったので質問させていただいたのですが、どうも状況の説明が不足だったようで申し訳ありませんでした。ともかくこれですっきりすることが出来ました。どうもありがとうございました。 -- ast 2006-09-26 (火) 08:59:26
  • k様、お忙しいところ回答有り難うございます。short型よりint型の方が、コードの量も少ないし、計算も速いというのはビックリしました。CPUって言うのは不思議ですね。勉強になりました。 -- 名無しさん 2006-09-27 (水) 08:12:53
  • 初版第6刷のP131から質問です。PUSHADの次に、MOV EAX,ESP PUSH EAXとしていますが、PUSHADでEAXをスタックに積んでいるのに、何故もう一度スタックに積むのでしょうか?ESPとEAXが同じになるのが、ミソなのでしょうか?それとも、EAXがスタックの一番上になるのがミソなのでしょうか? -- 名無しさん 2006-09-27 (水) 08:23:40
  • その質問への回答を十分に理解するには、p.454までを読破する必要があるでしょう。そこまで読んでも分からなかったらまた質問してください。現段階でも理解できそうな範囲で言うとしたら、そのMOVとPUSHはESPの値をスタックの一番上に置くためのものであって、ESPの値を保存するためではないということです。 -- K 2006-09-27 (水) 17:19:58
  • k様、回答有り難うございました。p454はまだずっと先ですけれど、えっちらおっちら読んでいきます。重ね重ね有り難うございました。 -- 名無しさん 2006-09-28 (木) 02:12:43
  • 初版第6刷のP140からの質問です。くだらないのですが、構造体のメンバは代入しない場合、勝手に0が代入されるのでしょうか?初期化しない変数の初期値は不定とあったので、疑問に思いました。 -- 名無しさん 2006-09-29 (金) 15:59:55
  • 変数をどこで宣言するかによって違うのですが、p.140のように関数の外で宣言した場合は、それが普通の変数であっても、構造体変数であっても、中身の初期値はすべて0になることが保証されています(C言語でのルールです)。 -- K 2006-09-29 (金) 16:52:45
  • k様、お手数をおかけして申し訳ございません回答有り難うございました。もうちょっとイイC言語の本買ってきます。 -- 名無しさん 2006-09-29 (金) 21:40:15
  • 初版第6刷のP141から質問です。今まで、harib4bで2度目のキーコードの受け取りに失敗するのは、cliをしてstiするまでの間に2度目の割り込み要求がくるため、2度目の割り込み要求が無視されるのだと思っていました。p89にも「割り込みフラグが0のとき、割り込み要求信号をとりあえず無視する」とありますし。ですが、「割り込み禁止の時に割り込み要因が発生したら 、割り込み許可になるまでその割り込みは待たされる 」と調べたら出てきました。このことが本当ならば、一度目のキーコードを受け取った後、すぐcliされるので2度目のキーコードも読み捨てが起きないような気がするのですが・・・(一度目の割り込みハンドラ呼び出し、cli、キーコード取得、sti、2度目の割り込みハンドラ呼び出しの順にならないのでしょうか?) -- 名無しさん 2006-10-03 (火) 02:09:04
  • 名無しさんへ。それはなかなかよい質問です。p.142に読み捨てに関する説明がありますが、それをここに抜き出します。「HariMainがE0を受け取る前に1Dや9Dがきてしまい、これを読み捨ててしまったようです」。・・・つまり読み捨て問題は割り込みハンドラで起きているわけではないのです。割り込みハンドラは正しく2つとも受け取っています。だけどHariMainのほうが追いつかなくて、E0を処理する前に1Dや9Dが来てしまい、ハンドラはkeybuf.flagが1になっているのでkeybuf.dataを更新することができず、結局「読み捨て」が起きるわけです(ハンドラの「とりこぼし」ではないことに注意)。名無しさんの、ハンドラ呼び出しとキーコード取得に関しての説明は完全に正しいです。 -- K 2006-10-03 (火) 08:33:31
  • k様、回答有難うございます。2回の割り込みハンドラはちゃんと2つキーコードを取得しているけれど(1度目E0、2度目1D)、2つの割り込みがほとんど同時に起きているから、2度目の割り込みのキーコードを覚える空きが無くて結果、1度目のキーコードと同じ内容の割り込みになってしまう(itiと。そして、HariMainに渡される内容は同じだから、cliしようがstiしようが、同じ内容を表示してしまう、という理解で大丈夫でしょうか?割り込みと言うのは凄い速さで起こるんですね。 -- 名無しさん 2006-10-03 (火) 14:50:26
  • 名無しさんへ。その後半の説明は正しくないように見えます。あっていると思われる部分:「2回の割り込みハンドラはちゃんと2つキーコードを取得しているけれど(1度目E0、2度目1D)、2つの割り込みがほとんど同時に起きているから、2度目の割り込みのキーコードを覚える空きが無くて」「割り込みと言うのは凄い速さで起こるんですね」。間違っていると思われる部分:「1度目のキーコードと同じ内容の割り込みになってしまう(itiと。そして、HariMainに渡される内容は同じだから、cliしようがstiしようが、同じ内容を表示してしまう」。 -- K 2006-10-03 (火) 16:07:25
  • HariMainからみると、データの受信は最初の一回(E0の分)しかやっていません。E0を二度表示しているわけではありません。・・・処理の流れ: HariMain実行中。割り込み発生。ハンドラがE0を受信。keybuf.dataにE0を代入。HariMainに帰った瞬間に、またすぐに割り込み発生。1D受信。keybuf.dataに書き込みたかったけど、keybuf.flagが1なので書き込まない(読み捨て)。HariMainにやっと復帰。HariMainはkeybuf.flagが1なのでkeybuf.dataの内容を受信。HariMainは1Dの存在すら知らない。 -- K 2006-10-03 (火) 16:08:09
  • k様、何度もお手数をおかけして申し訳ございません。明確な回答有難うございます。最後にもう一つだけ質問することをお許しください。「ハンドラがE0を受信。keybuf.dataにE0を代入。」この間にさらに割り込みが3つ起こったとすると、その3つの割り込みはPICに記録(保存)されて、FIFO型の順に3回「HariMainに帰った瞬間に、またすぐに割り込み発生。ハンドラ呼び出し」として処理されていくのでしょうか?それとも今は割り込み禁止中として、無視(破棄)されるのでしょうか?また、PICが記録できる場合、どのくらい割り込みの数を覚えられるのでしょうか? -- 名無しさん 2006-10-04 (水) 03:12:09
  • PICが保留できる割り込みの数は、一つのIRQについて一つです。つまりIRQの番号が違えば、最大で15個までは保留できるというわけです。でもこれだとE0の処理中に1Dを保留できた理由が分かりません。実はこれはキーボードコントローラのおかげです。キーボードコントローラはたぶん10個以上のキー入力をためておくことができます(たぶん厳密にいくつまでためられるかは機種依存でしょう)。それで1Dは取りこぼさずに済んでいたのです。・・・キーボードコントローラは IN AL,0x60 が実行されたときにまだ内部にデータを持っていたら、割り込みを発生させています。したがってキーボード割り込みを処理する際には、 IN AL,0x60 を実行するまでにPICに対して割り込み処理終了を通知しておく必要があります(そうでないとせっかく次のキーボード割り込みが起きたのにPICは前の割り込みの処理中なので無視してしまいます)。 -- K 2006-10-04 (水) 23:13:02
  • k様、回答有難うございます。理解できました。割り込みは難しいですね。沖電気のmsm82c59a-2の解説を読んで自分なりにも調べたんですが、コンピュータは複雑だなと思いました。 -- 名無しさん 2006-10-05 (木) 01:35:53

リロード   新規 編集 差分 添付   トップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新のRSS
Last-modified: 2007-01-29 (月) 20:42:38 (4376d)