SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

MASMとなでしこによるオリジナルコンパイラの制作

MASMとなでしこによるオリジナルコンパイラの制作 1

コンパイラとアセンブラの基礎知識

四則演算とスタック

 四則演算とスタックについて見ていきます。

test8
.586
.model flat, stdcall

include iolib.inc
includelib iolib.lib
include kernel32.inc
includelib kernel32.lib

.data
    kekka dd 0
    STR0 db "13 + 35は、", 0
    STR1 db "54 - 37は、", 0
    STR2 db "7 * 8は、", 0
    STR3 db "42 / 7は、", 0

.code

_start:
    invoke OutputString, NEAR32 PTR STR0
    mov eax, 13
    push eax
    mov edx, 35
    push edx
    pop edx
    pop eax
    add eax, edx
    push eax
    pop eax
    mov kekka, eax
    invoke OutputInteger, kekka

    invoke OutputLetter, 13
    invoke OutputLetter, 10

    invoke OutputString, NEAR32 PTR STR1
    mov eax, 54
    push eax
    mov edx, 37
    push edx
    pop edx
    pop eax
    sub eax, edx
    push eax
    pop eax
    mov kekka, eax
    invoke OutputInteger, kekka

    invoke OutputLetter, 13
    invoke OutputLetter, 10

    invoke OutputString, NEAR32 PTR STR2
    mov eax, 7
    mov edx, 8
    push eax
    push edx
    pop edx
    pop eax
    mul edx
    push eax
    pop eax
    mov kekka, eax
    invoke OutputInteger, kekka

    invoke OutputLetter, 13
    invoke OutputLetter, 10

    invoke OutputString, NEAR32 PTR STR3
    push 42
    push 7
    pop ebx
    pop eax
    mov edx, 0
    div ebx
    push eax
    pop eax
    mov kekka, eax
    invoke OutputInteger, kekka

    invoke OutputLetter, 13
    invoke OutputLetter, 10

    invoke ExitProcess, 0
end _start

 少し見にくいアセンブリですが、一つ一つ解釈していきます。

mov

 movはmoveの略で、値の代入に使います(moveの直訳は移動ですが、アセンブリではコピーと同じような意味です)。

mov (代入先),(代入するもの)

 例えば、

mov eax, 13

 では、eaxに13を代入します。C言語風に書き直すと、

eax=13;

 となります。

レジスタとスタック

 レジスタとは、一時的なデータ領域のことで、多くの種類があります。本稿では、以下の4つを用います。

  • eax
  • ebx
  • ecx
  • edx

 このうち、eaxはWin32APIの戻り値などによく使われますが、それについては後述します。

 「あれ、eaxedx.dataで宣言していないじゃないか」という方は鋭い。実は、レジスタは宣言が不要なのです。CPUが直接持っているようなものです。レジスタへの代入にはmovも使われますが、スタックもよく使われます。

 「スタック」は、後入れ先出し(最後に入れたものが最初に出てくる)のデータ構造で、皿を積み重ねるイメージに近いです。皿に皿を重ねること(データの格納)を「push」、一番上の皿を取ること(データの取り出し)を「pop」と言います。

スタックの操作
スタックの操作

 popでは常に一番上のものが取り出されるので、一番上に何があるか把握しておく必要があります。これは非常に大事なので覚えておいてください。

 さて、これを何に使うかと言うと、一部の変数はスタックを通さないとmovできないものがあります。そして、これから説明する四則演算もその一つです。

四則演算

 足し算、引き算は極めて覚えやすく、次のとおりです。movに似ているかと思います。

足し算の例
add tasareru, tasu
    同等のC言語(足し算)
    tasareru = tasareru + tasu;
    
引き算の例
sub hikareru, hiku
    同等のC言語(引き算)
    hikareru = hikareru - hiku;
    

 なぜこういうのにスタックが必要なのかと言うと、C言語風のものをよく見てください。足される(引かれる)数が入っている変数に計算結果が入ります。これでは、足される(引かれる)数の元の値が分からなくなります。そこで、スタックを使います。

 たとえば前述のコードでは、足し算を次のように行っています。

スタックを使った足し算
mov eax, 13    ; レジスタに13を代入

push eax       ; 13の入ったレジスタをpush
               ; スタックの中身 …… [13]

mov edx, 35    ; レジスタに35を代入
push edx       ; 35の入ったレジスタをpush
               ; スタックの中身 …… [35] [13]

pop edx        ; popする
               ; スタックの一番上には35が入っているのでedxには35が入る
               ; スタックの中身 …… [13]

pop eax        ; eaxにスタックの一番上=13が入る

add eax, edx   ; popしたスタック同士で足し算

push eax       ; 結果(eax)をもう一回push
pop eax        ; そして、popします

mov kekka, eax ; 結果を格納する変数にeaxを入れる

 スタックを使うと、足される(引かれる)数を忘れる事なく残しておく事ができます。もちろん、それらを残しておく必要がなければ、スタックを使う必要はありません。しかし、スタックを使う癖をつけておくと、長いプログラムが正しく動かない時のデバッグに助かります。

 掛け算、割り算は少し難しくなります。

掛け算の例
mul edx
    同等のC言語(掛け算)
    eax = eax * edx;
    
割り算の例
div ebx
    同等のC言語(割り算)
    eax = eax / ebx;
    edx = eax % ebx;
    

 スタックのeaxに依存しています。しかも、割り算では余りをedxに格納しています。そのためeaxは必須です。ちなみに、割り算の「A % B」は、「AからBを割った余り」を表しています。

 また、割り算をする時、レジスタのedxを初期化しなければいけません。さもないと、保護エラーが発生します。筆者は、これに何回も泣かされました。

まとめ

 今回は、アセンブリの文法からWin32APIの呼び出し、スタックについて説明しました。この他にも条件分岐などがありますが、少し複雑になりますのでアセンブリの雰囲気に慣れてからにします。スタックの性質は、コンピュータについて深く掘り下げている高校ではテストにも出るようです。

 筆者は、まだ作文が苦手ですので、分からないところがあれば遠慮なく筆者のHPからメールでお問い合わせください。

次回予告

 次回は、いよいよ「なでしこ」に触れ、コンパイラの制作に取り掛かります。もし簡単な構文の説明が早く終わった場合は、コンパイラに必要な要素「コマンドライン」についても言及する予定です。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
MASMとなでしこによるオリジナルコンパイラの制作連載記事一覧

もっと読む

この記事の著者

KMY(かみぃ)

とあるごく平凡な中学生。兵庫県在住。日本語プログラミング言語「なでしこ」に惹かれ、たくさんのプログラムを作り利用している。なでしこ以外にも、他の言語を心得ており、HTMLがなでしこの次に得意であり、Perlが第3位(かも)。ベクターにも多彩な作品を残している。作文がど苦手。KMYpage

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/505 2008/09/02 13:02

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー