アセンブラの意味と使い方について教えてください

このQ&Aのポイント
  • アセンブラとは、機械語プログラムを記述するための言語です。
  • アセンブラのコードは、バイトやワード単位で指定することができます。
  • セグメント間ジャンプ命令を使用することで、CSレジスタに特定の値をロードすることができます。
回答を見る
  • ベストアンサー

このアセンブラの意味を教えて下さい

アセンブラ初心者です。「はじめて読む486」を読んで勉強しているのですが、いくら調べても分らないのでどうぞ教えて下さい。次の2つのプログラムが分りません。 ------------------------------------------ db 0eah dw offset set_cs_desc2 dw 20h set_cs_desc2: 以下プログラムが続く --------------------------------- セグメント間ジャンプ命令によってCSレジスタに0020hをロードすると本にあるのですが、先ずdb、dwとは何を意味するのでしょうか。単にバイト、ワードを指定しているのでしょうか?そうだとしたらなぜdb、dwと指定しているのか分りません。 また0eah,20hが何を意味しているのか分りません。 出来れば1行ごとに詳しく教えて戴ければ嬉しいです。 また ------------------------------ db 0eah dw offset set_cs_desc3 dw seg set_cs_desc3 set_cs_desc3: move命令などが続く _text ends end ------------------------------------ セグメント間ジャンプ命令によってCSレジスタに_textをロードすると本にはあるのですが、上のプログラムと同様、0eah,db,dwが分りません。 またsegは何を意味するのか分りません。お手数だとは思いますが、これも1行ごとに詳しく解説していただけないでしょうか? そして2つのプログラム共通に分らないのが、なぜこのコードでCSレジスタにロードする事になるのか分りません。 多分意味している事は簡単な事なのだろうと思うのですが、いろいろ調べても全く手がかりがネットや他の本にもなく苦労しています。 初心者なので出来れば簡単な言葉で教えて戴ければ幸いです。 よろしくお願いいたします。

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

  • ベストアンサー
  • KEIS050162
  • ベストアンサー率47% (890/1879)
回答No.2

もう少し易しい、86系のアセンブラ入門から勉強されることをお勧めします。 質問者殿の指摘の部分は、セグメントジャンプ(FAR JUMP)の典型的な手法ですが、それ以前に、DB、DWの疑似目命令、0eah,020hの意味などが分かるレベルになってからもう一度挑戦するのが良いかと思います。 少なくとも、この命令群はいきなり初心者が扱う様なコードではないと思います。 一応ある程度わかる範囲で解説します。 DB、DWの疑似命令は#1さんの解説通りです。メモリ上にデータを直接記述方法です。それぞれバイト、ワード単位で記述します。 0eah、020hは、16進数の表記方法で、それぞれ00EA H(Hex)、0020 H(Hex)を表します。 ここまでは、アセンブラ入門の一番最初の方で出て来ますので、入門書などで再確認してください。 つぎに、セグメントについてですが、86系のCPUは、基本的には16ビットのアドレスレジスタ(OFFSET)の空間でプログラムのジャンプやデータの参照を行います。ただし、これだけだとそれ以上大きなメモリ空間が記述出来ないのでセグメントレジスタ(SEG)を使って、24ビットのアドレス空間を表現します。 例) SEG 0C000H で OFFSET 00A0H の場合、アドレスは、SEG×10H + OFFSETで表し、この例だと、0C00A0H となります。 セグメントを制御するレジスタは、CS(CODE SEGMENT)、DS(DATA SEGMENT)、SS(STACK SEGMENT)があり、それぞれプログラムの実行、データの参照、スタックの参照用のセグメントレジスタとなります。 セグメントの扱いは86系の目玉となります。アセンブルし、マシンコードとなったオブジェクトがメモリ空間上にどの様にマップされるのか、などをイメージしながら理解していってください。 問題の、DB 0eaH … で始まる命令群ですが、これはかなり特殊な用途で使うものだと思います。 アセンブラで記述する時、ニーモニック(ロード命令やジャンプ命令の表記法)を使って、アセンブルするのが一般的ですが、時には、マシンコードを直接DB、DW命令で打ちこむ手法が使われます。(この手法自体はさほどトリッキーではありません)。 もともとフォンノイマン型のコンピュータ(ほとんどのコンピュータはこれです)は、データもプログラムコードもメモリ空間上にデータとして表すことが出来るので、命令コードをデータとして打ちこんでも良い訳です。 今回の例では、打ちこまれたデータ 0eah は、データとしては16進数の0EAHですが、命令レジスタではこれはセグメントジャンプを表すマシン語に解釈され、次の続くデータは、このマシン後のオペランド(OFFSET、SEG)と解釈されます。 最初の例では、オフセットはset_cs_desc2で定義されるアドレスのOFFSET値と直接0020Hのセグメント値がオペランドとして与えられています。 次の例では、オフセット値は同じですが、セグメント値は、set_cs_desc2で定義されるアドレスのセグメント値が参照されています。 set_cs_desc2は、コーディング~アセンブル段階では仮決定されますが、その後リンカー~ロケータの処理を経て解決され具体的な値が決定されます。 従って、それぞれ、記述されたセグメント、オフセットで表されるアドレスへのFAR JUMP(セグメントジャンプ)となります。具体的には、CODE SEGレジスタ(CS)に与えられたセグメント値、プログラムカウンタに与えられたオフセット値が入力される、ということになり、そこのアドレスに制御が移るということになります。 かなり端折った説明ですが、概略はこの様な感じになるかと思います。 後半の方は少し難しいかもしれませんが、ヒントになれば幸いです。 ご参考に。

osiete-pc
質問者

お礼

詳しいご回答、本当にありがとうございます。 お陰でぼんやりとではありますが、このプログラムの意味するところが分ってきました。 アセンブラの解説書は本当に基本的なものと高度なものとに分かれるので、その中間に位置するものがあれば良いのですが、なかなか見つかりません。若しよろしければ、またお手数になって申し訳ないのですが、良いサイト、解説書などがあれば推薦して頂ければ幸いです。

その他の回答 (2)

  • nda23
  • ベストアンサー率54% (777/1415)
回答No.3

DB 0EAh これは1バイトの領域を確保し、初期値を 16進数のEAにするという擬似命令です。 動作が伴うわけではありません。単に データ領域を定義しただけです。 後方の"h"は16進直定数を表わし、値の 最初がA~Fの場合は前に0を置かないと シンボルと間違えるのでこうします。 0020hも16進直定数です。 DWも同じで2バイトの領域を確保します。 DW xxx のxxxは同じくその初期値です。 DD擬似命令と言うのもあり、オフセットと セグメントを同時に定義できます。 DW OFFSET set_cs_desc3 DW SEG set_cs_desc3       ↓ DD set_cs_desc3 OFFSET擬似命令はオペランドのセグメント 先頭からの相対変位を表わします。 SEG擬似命令はオペランドのセグメント アドレスを表わします。 OFFSETはリンク時に確定します。従って、 EXEプログラム内では静的な定数です。 これに対し、SEGは実際にプログラムが ロードされるアドレスにより変動するため、 静的な値ではありません。 セグメントを参照する部分はEXEヘッダに 情報があります。OSはプログラムを実行 する際、メモリにプログラムをロードして、 確定したセグメントアドレスをEXEヘッダの 情報に従って、埋め込みを行います。 しかる後に、実行開始点に制御を渡します。 勿論、OSの稼動部分とプログラムがロード された空間はセグメントが違うので、制御を 渡す時はセグメント間ジャンプ(実際はCALL) を使うということです。セグメント間ジャンプ 命令の実際の動作は以下の通りです。 CS←ジャンプ先のセグメントアドレス IP←ジャンプ先のオフセットアドレス 提示されたプログラムがセグメント間ジャンプ するのではありませんよ。誤解の無いように。 尚、セグメント+オフセットというのは16ビット 時代の古い考え方で、互換性のために残って いますが、現在の32ビットプログラミングでは フラットアドレスになっており、セグメントとか オフセットのような使い方はしません。単に アドレスと言います。よって、データやコードの アドレスを格納する際にはDD擬似命令を使い ます。

osiete-pc
質問者

お礼

セグメントとオフセットの関係は前々から面倒に思っていたのですが、昔の名残なんですね。 一応理解はしていたものの、リンク時にどうなるかなど、さらに理解が深まりました。 本当に詳しい解説ありがとうございます。お陰さまで少しづつこのプログラムの意味が分ってきました。

  • kmetu
  • ベストアンサー率41% (562/1346)
回答No.1

> db、dwとは何を意味するのでしょうか .DB疑似命令 アセンブリ言語への招待 Part 3 アセンブリ言語による本格的なプログラミング http://ueno.cool.ne.jp/nvaca/asm3.html こちらを参照してください。

osiete-pc
質問者

お礼

ご回答ありがとうございます。 dbとはバイト単位でデータ領域を確保するので、db 0eahとは、0eaをメモリに書き込むという認識でよろしいでしょうか? 上のプログラムはプロテクトモードからリアルモードに移行するものの一部なのですが、なぜ0eah等いろいろな値を指定しているのでしょうか?そこが全く分りません。よろしければ行ごとに詳しく教えていただけないでしょうか?よろしくお願いいたします。

関連するQ&A

  • アセンブラに関する質問

    ↓のソースをMASMでコンパイル&リンクして実行すると  入力まではできるのですが、入力した直後に   「このプログラムで無効な処理が発生したため、強制    終了されます。全てのプログラムを、終了してから    再起動してください」 と表示され、そのメッセージが表示されたウィンドウの下の方の「詳細」をクリックすると    「プログラムで一般保護エラーが発生しました     エラーが起きたアドレス 9A00:10000     サービスへの割り込み なし」     と表示されました     実行したのは↓にソースですが、何がいけなくて     このエラーが出たのでしょうか・・(OSはME) CODE SEGMENT ASSUME DS:CODE,CS:CODE,ES:CODE,SS:CODE ORG 100h START: mov ah,0Ah mov dx,offset BUFF int 21h mov ah,09h mov dx,offset BUFF2 int 21h BUFF db 54,87,5 dup(?) BUFF2 db 'testtest' '$' code ends end start

  • NASMかNASKの文法の本

    NASMかNASKのアセンブラを使っているのですが、MASMと構文が異なっている?せいか、エラーなりました。 MASMでは DW offset ADR_KOKO DW seg ADR_KOKO でOKだと思いますが、NASM/NASKではどうするのでしょうか? NASM,NASMの文法など詳しく載っている本などありますか?(洋書でも構いません。) DW 0 ; A---> オフセット DW 0 ; B---> セグメント ADR_KOKO: ;ここのオフセットとアドレス値をA,Bにセットしたい mov eax, 1  ... RET

  • ハイパースレディングのレジスタについて

    ハイパースレディングのレジスタについて ハイパースレッデイングのCPUで2つのスレッドA,Bを動かすとする。 このときAの実行状態を示す汎用レジスタやプログラムカウンタと     Bの実行状態を示す汎用レジスタやプログラムカウンタの扱いはどうなのでしょうか。 次の2つの方法が考えられる。 (1) レジスタのロード、実行、レジスタのセーブを繰り返す方法。     CPU内に高速なメモリを持ち、実行前にレジスタに値をロードして、命令を実行して、レジスタの値を保存を繰り返して、A,Bのスレッドを実行する方法。 (2) A用のレジスタとB用のレジスタを2組用意して、相互に切り替えながら実行する方法。     Aを実行するときはA用のレジスタを使用して、Bを実行するときはB用のレジスタを使用する方法。 の2つが考えられるが、それとも他の方法があるのでしょうか。 それに関連して、1度に実行する機械語命令の個数はいくつなのでしょうか。 スレッドAの機械語命令を実行して、切り替えてBの機械語命令を実行するときに、 Aの1命令を実行してから、Bの1命令を実行する。1命令毎に切り替えるのでしょうか、 それともAの数個の命令を実行してから、Bの数個の命令を実行するのでしょうか。 このときスレッドを切り替える際に1度に実行する機械語命令の個数はいくつでしょうか。 ご存知の方がおりましたら、教えて下さい。

  • 文字を表示するファンクションコールについて

    アセンブリ言語プログラムについての質問です。 MASM32を使っています。AXレジスタの数値をah→表示、al→表示というプログラムを作ったのですが、al→表示の部分がうまく機能しせません。以下にプログラムを書きます。 (1)mov ax,3132h (2)mov dl,ah (3)mov ah,02h (4)int 21h (5)mov dl,al (6)mov ah,02h (7)int 21h (分かりやすく番号をふっています。実際のプログラムには番号はふっていないです。) 具体的どこが機能しないかというと、(5)番目の命令のalレジスタの内容をdlレジスタに転送するという命令が機能しません。デバックのT命令で確認したところ(5)番目の命令がNOPとなっていました。 このプログラムを実行すると結果的に表示されるのは「11」という文字です。(本来は12と表示したい。) 質問 なぜ(5)番目の命令がnopとなるのでしょうか?

  • 情報処理概論

    今情報処理概論という勉強をしています。教科書をよんでもわからないので2つ質問です。 1.プログラムカウンタと命令レジスタ  例えばプログラムカウンタが”2256040”であるとき、次のフェッチサイクルではこの番地からはじまる命令が命令レジスタに移され移された命令が4バイト命令であれば、プログラムカウンタには4が加えられる。、と教科書に書いてあるのですがチンプンカンプンです。誰かわかりやすいように説明していただけますか? 2.演算装置について  例えば”01001010 11001101”と表記されている命令は、あるコンピュータでは”1010 11001101”にある16ビット符号付整数を演算装置のレジスタ(アキュムレーター)の内容に加え、その結果(和)をアキュムレーターにセットすることを意味する。、と教科書に書いてあります。まったく意味不明なので誰かわかりやすく説明できる人回答お願いします。 ながくなりましてすいません。よろしくお願いします。

  • 命令レジスタとデコーダ

    翻訳の勉強をしていて、プログラムについては門外漢です。 「命令レジスタには機械語命令が格納される」「命令レジスタに格納された命令をデコーダが解読する」とテキストに書かれているのを読みました。 機械語は既に0か1であると思うので、それをどう解読するのか、「解読」の意味が分かりません。 詳しい方、できれば簡潔に解説をお願いします。

  • アセンブリ:FCのファイルオープンについて

    アセンブリ:FCのファイルオープンについて ファイルオープンのファンクションコールについて質問させてください。 うまく伝えられるか不安なので、いま陥っている現象を順番に書かせていただきます。 まずエディタで、 ---------------------------------- MOV AH , 3DH MOV AL , 00H MOV DX , offset FNAME INT 21H FNAME DB 'C:\xyz.txt',00H ---------------------------------- という簡易なプログラムを記述しました(擬似命令は省いています) これをアセンブルすると、 --------------------------------------- CS:0100 B43D MOV AH,3D CS:0102 B000 MOV AL,00 CS:0104 BA0901 MOV DX,0109 (*注) CS:0107 CD21 INT 21 CS:0109 43 INC BX ・ ・ --------------------------------  となるのですが、このとき AX=0003  CY となり、ファイルオープンに失敗してしまいます。 理由がまったくわからないので、デバックの直打ちで 0200 DB 'C:\xyz.txt' と格納してから、(*注)である命令を MOV DX,0200 に打ちかえれば、 AX=0005  NC となって無事にオープンできるみたいです。 なお、ファイルオープンに限らず、ファイル作成でも同じでした。 エディタでアセンブル( DX , 0109 ) だと失敗し、 デバッグ直打ち( DX , 0200 ) だと成功します。 これはいったい、どういう理由からなのでしょうか? 何冊か本を読んでみたのですが、書かれているのはコードの記述のみなので困っています。 わかる方がおられましたら、ご教授ください。 WINXP:MASM32で行っています。

  • GCCの.cfi_系について

    アセンブラソース変換ソフトを作ってます。 タイトル通り .cfi_def_cfa_register %rbp .cfi_offset %rbp, -16 etc... はどのような意味でしょうか? 疑似命令なのでアセンブリしたときは入ってなく、動作に影響はありません。

  • 非常に限定された条件での8バイト加算

    アセンブリプログラム上で16ビット同士を加算したいと考えています。 ただ、非常に条件が限定されていて、 【簡単な構成について】 ・レジスタは8ビットAレジスタ一つのみ ・8ビット演算器(ALU)は一つのみ ・条件コードはZフラグのみ(ただし、書き換わるのは命令7.、8.でのみ) 【使える命令】 1.Aレジスタに即値をロード 2.Aレジスタに指定アドレスのデータをロード 3.Aレジスタから指定アドレスにストア 4.無条件分岐 5.Aレジスタand即値=0ならば分岐 6.Aレジスタor即値=0ならば分岐 7.Aレジスタと即値のandをとって書き戻し 8.Aレジスタと即値のorをとって書き戻し 9.Aレジスタと即値を加算して書き戻し a.Aレジスタと指定アドレスのEORをとって書き戻し b.Aレジスタと指定アドレスのデータを加算して書き戻し c.間接アドレスのデータをAレジスタにロード d.Aレジスタの内容を間接アドレスにストア e.Aレジスタから即値を減算して書き戻し f.Aレジスタから指定アドレスデータを減算して書き戻し 普通に考えるならば、下位8ビット同士の加算、上位8ビット同士と下位8ビットのキャリーを加算すれば出来ます。 しかしながら、この限定された条件に於いてはなんらかの自由に使えるフラグ、もう少し汎用的に使える分岐命令が無ければ無理だと個人的には考えています。 出来るか、出来ないか、だけでも結構ですので、ご教授お願いします。

  • マイクロプロセッサのZ80について学校で課題がでたのですが、

    マイクロプロセッサのZ80について学校で課題がでたのですが、 5100H番地に50H、5101H番地に10Hをキー入力であらかじめ書き込む。 4200H番地に以下のプログラムを書く。   (1)5100H番地、5101H番地の内容をそれぞれB、Cレジスタに取り込んだ。   (2)AレジスタにBレジスタの内容を転送し、AレジスタとCレジスタを加算し、その結果を5200H番地に格納した。   (3)AレジスタにBレジスタの内容を転送し、AレジスタからCレジスタを減算し、その結果を5201H番地に格納した。   (4)モニタに戻した。  JP  2006H  C30620 アセンブラプログラムーーーーー機械語 (1) LD A , (5100H)ーーーーー 3A0051 LD B , Aーーーーー 47 LD A , (5101H)ーーーーー 3A0151 LD C , A ーーーーー 4F (2)LD A , B ーーーーー 78 ADD A , C ーーーーー 81 LD (5200H) , A ーーーーー 320052 (3)LD A , Bーーーーー 78 SUB A , C ーーーーー 91 LD (5201H) , Aーーーーー 320132 (4)JP 2006H ーーーーー C30620 このプログラムコードの最適化(命令数の削減)を行え。 という課題がでました。どうすればよいかわかりません。どなたかおしえてください。

専門家に質問してみよう