20260511_2


  • マルチプロセスと同様にメモリについても仮装記憶をもつ

    • 実際のメインメモリの容量よりも大容量のメモリがあるように見せる
    • あふれた分はストレージへ
    • 仮想アドレス空間とメモリ保護
      • 各プロセスが独立したアドレス空間と独立したメモリを利用で起用に
      • 同じ番号のアドレスが複数扱えるようになる
  • コンピュータには機械語しか入れられないが、機械語に近い機械語プログラムと人間の思考の間には大きなギャップがある

  • ギャップをある程度埋められる高級プログラミング言語の必要性

    • CPUには存在しないデータ型や言語機能を提供して、命令を行えるように
    • 翻訳はコンパイラが頑張ってくれる
    • アセンブリの場合はアセンブラが対応、高級言語をアセンブリに翻訳する段階を挟む場合も
  • 翻訳過程を隠蔽することによって、ハードウェアの接点が高級言語のプログラムとしてとらえられるように→インタプリタ

    • 対話的に実行できる
    • インタプリタがプログラムを解釈しながら実行(速度ではコンパイラに劣り、実行のたびにインタプリタが必要)
  • コンパイラとインタプリタを併用する

    • VMの機械語プログラムに高級言語をコンパイルする
    • そのあとVMをインタプリタで実行する

英語の本を読むたとえ: コンパイラが翻訳、インタプリタが通訳だと思うとよいらしい


アセンブリ言語の命令は

オペレータ+オペランド1+オペランド2

という形式
これを機械語に変えるので

オペコード オペランド1 オペランド2 のような形式

(順番はものによって異なる)

命令長は一般的にRISCで1ワード(64bitとか)で、CISCでは様々、命令バイト列の一部を切り取ったものがフィールド

命令セットの分類

オペランドにメモリアドレスを取れるか?

  • レジスタ-レジスタ型アーキテクチャ
    • RISC系、arm64とか、loadstoreでしかメモリを使えない
  • レジスタ-メモリ型
    • CISC系、x86とか
  • メモリ-メモリ型
    • CISC系VAXなど

下のやつは上のやつを包含している

オペランド処理が多いとハードウェアを複雑にしないといけないが、実行命令数は少ない

オペランドが少ないと命令数を増やさざるを得ないが、パイプライン処理で有利


レジスタ-レジスタ型

  • 演算命令のオペランドは最大で3つ(ソース2,デスティネーション1)
  • 演算命令のオペランドはレジスタか即値
    • 実行命令数はどうしても増えてしまう
  • オペランドや命令が単純で命令を固定長にできる
  • たくさんのレジスタをもつ
    • メモリアクセスを減らして高速化を図る
    • コンパイラ側でレジスタ管理を最適化する
add reg1, reg2, reg3 //reg1<-reg2+reg3
add reg1, reg2, 定数 //reg1<-reg2+定数
load reg1, 定数(reg2) //reg1<-[reg2+定数]
store reg1, 定数(reg2) //[定数+reg2]<-reg1

[]の中身がメモリアドレス
上の中の定数は機械語の中で(メモリアドレスではなく)即座に定数として解釈される→即値


レジスタ-メモリ型

  • 演算命令のオペランドは最大で2つ
    • ソースが2つで、ソースの1つはデスティネーションを兼ねる
    • ロードを兼ねた演算が可能
    • アドレスはレジスタで指定するが、即値による指定も可能
  • 命令長は様々
    • プログラムサイズを小さくするために高級な命令を採用
    • オペコードを解読するまで命令長が不明
      • 命令フェッチや出コードに負荷がかかる
	mov    eax, 0  ;eax<-0
	mov    ecx, 10 ;ecx<-10
L1
	add    eax, ecx ;eax<-eax+ecx
	sub    ecx, 1   ;ecx<-ecx-1
	jnz    L1

アドレス指定

オペランドデータ(オペランドの実体)はどこにある?

  • 命令内(即値)
  • レジスタ内
  • メモリ内

直接アドレス指定
メモリ/レジスタに存在するオペランドデータを直接指定する(イメージしやすい方法)
add r1, r2, r3とか、add r1, [100]とか

間接アドレス指定
実効アドレスをメモリやレジスタに置く
add r1,[r3]みたいな方法
実効アドレスを実行中に変更できるのが強み(絶対アドレスでも不可能ではないけど、copyfailしかねない)

相対アドレス指定
基準アドレス+変位として指定する

プログラムカウンタの値を基準アドレスとして、そこから指定の変位だけずれた位置を実効アドレスとする

命令とオペランドを一緒に動かせばメモリのどこに置いておいてもよくなって便利(リロケータブル)

ifやwhileなどのjump先を指定するときにも絶対アドレス指定だと毎回最初に戻ってしまうけど、相対アドレスでは近くにジャンプしやすくて使いやすい

ベースレジスタに基準アドレスを持たせる場合もある→再帰呼び出しなどで利用できる、逆も可能だし、インデックスも基準もレジスタにおいてもいい

どの方法も複数の命令を使えば実現できる