プリンキピア

第5章アルゴリズムのハードウェアによる実現:コンピューターシステム設計

5.4 Machine-Level Program Representation5.4 機械レベルでのプログラム表現

Learning Objectives学習目標
By the end of this section, you will be able to:
この節を終えると、次のことができるようになる。
• Discuss x86-64 Intel processors and their architectures
• x86-64 Intelプロセッサとそのアーキテクチャーについて論じる。
• Differentiate between assembly and machine languages
• アセンブリ言語と機械語を区別する。
• Explain basic concepts of assembly language and the types of operations
• アセンブリ言語の基本概念と演算の種類を説明する。
When you write a program in an HLL, there are several steps that need to be performed before the processor can start executing the code. Refer to Figure 4.18 for a high-level view of the process.
英語のヒント
HLLでプログラムを書くと、プロセッサがそのコードの実行を開始できるようになるまでに、いくつもの手順を実行する必要がある。処理全体の概要は図4.18を参照してほしい。
Let us assume you write your program in C and your program is spread over several source files for ease of management. As you now know, the first step is to go through the compiler. The compiler is totally oblivious to the fact that the multiple source code files belong to the same program; it just takes each file separately and generates the corresponding assembly language file for each one of them. If the input is three C files, the output of the compiler will be three assembly language files.
英語のヒント
Cでプログラムを書き、管理しやすいように複数のソースファイルに分けているとしよう。すでに学んだように、最初の段階はコンパイラを通すことである。コンパイラは、複数のソースコードファイルが同じプログラムに属していることをまったく認識しない。各ファイルを個別に受け取り、それぞれに対応するアセンブリ言語ファイルを生成するだけである。入力が三つのCファイルなら、コンパイラの出力も三つのアセンブリ言語ファイルになる。
The next step is to take these language files and translate them to machine code files, also known as object files or binary files. Here too, the assembler is oblivious to the fact that the input assembly files do not belong to the same program, so it translates them separately. The first tool in this workflow that recognizes that all the files belong to the same program is the linker. The linker takes all the generated object files, looks for needed libraries, and links everything together into one executable file. Linked libraries are needed because it is very unlikely that programmers write self-contained code. You still use I/O, for example, for printing something on the screen, but you have not implemented those functions yourself—or you use mathematical functions someone else implemented. A library linked at this step is called a static library.
英語のヒント
次に、これらの言語ファイルを受け取り、機械語ファイルへ翻訳する。機械語ファイルは、オブジェクトファイルやバイナリファイルとも呼ばれる。ここでも、アセンブラは入力されたアセンブリファイルが同じプログラムに属していないという事実を認識せず、個別に翻訳する。この作業手順の中で、すべてのファイルが同じプログラムに属すると初めて認識するツールが、リンカーである。リンカーは生成されたすべてのオブジェクトファイルを受け取り、必要なライブラリを探し、すべてを結合して一つの実行可能ファイルを作る。ライブラリの結合が必要なのは、プログラマーが完全に自己完結したコードを書くことは、まずないからである。たとえば画面への表示などの入出力を使うが、その機能を自分で実装しているわけではない。また、ほかの人が実装した数学関数を使う場合もある。この段階で結合するライブラリを、静的ライブラリという。
At this stage, you have an executable file residing on your disk until you decide to execute it by typing a command, clicking an icon, or even saying a command. At that moment, a part of the operating system, called the loader, loads the executable into the memory and arranges its content in a specific way to make it ready for execution by the processor. A dynamic library is when more libraries may be linked during execution or while the program is running.
英語のヒント
この段階で、ディスクには実行可能ファイルが保存されており、コマンド入力、アイコンのクリック、あるいは音声コマンドによって実行すると決めるまで、そのまま置かれている。実行する時点で、OSの一部であるローダーが、実行可能プログラムをメモリに読み込み、プロセッサが実行できるように内容を所定の形に配置する。実行時やプログラムの動作中に追加で結合されるライブラリを、動的ライブラリという。
This section takes a closer look at assembly language. As an example of a widely used assembly language ISA, we will look at x86 ISA used by Intel and AMD processors. But before we delve into this, we need to ask a simple question: Why learn assembly language? Will you ever need to write code in assembly language? Most likely not, except in rare cases where you are developing some part of an operating system, a device driver, or any other application that requires very low-level manipulation. However, by looking at the assembly language generated by the compiler for your code, you can find innovative ways to optimize your code, detect hidden bugs, and reason about the performance of your code once you execute it.
英語のヒント
この節では、アセンブリ言語を詳しく見る。広く使われているアセンブリ言語のISAの例として、IntelとAMDのプロセッサが使うx86 ISAを取り上げる。しかし、その前に、簡単な問いを考える必要がある。なぜアセンブリ言語を学ぶのだろうか。実際にアセンブリ言語でコードを書く必要があるのだろうか。OSの一部、デバイスドライバー、あるいは非常に低いレベルでの操作が必要なアプリケーションを開発するような、まれな場合を除けば、おそらくない。それでも、自分のコードからコンパイラが生成したアセンブリ言語を見ると、コードを最適化する新たな方法を見つけたり、隠れたバグを検出したり、実行時の性能について考えたりできる。

Intel Processors and Related ArchitecturesIntelプロセッサと関連アーキテクチャー

You may recall that each processor family understands a set of instructions, which is the ISA. The family of processors from Intel and AMD share the same ISA called x86 (x86-64 for the relatively newer version for later processors). This ISA has a long history that dates back to the 1970s. Figure 5.16 gives a quick glimpse at how things evolved. The figure does not show every single processor from Intel but instead focuses on some milestones.
英語のヒント
各プロセッサファミリーが理解する命令の集合がISAであることを、思い出そう。IntelとAMDのプロセッサファミリーは、x86という同じISAを共有している(後の世代のプロセッサ向けの比較的新しい版はx86-64である)。このISAには、1970年代までさかのぼる長い歴史がある。図5.16は、その進化を簡単に示している。Intelのすべてのプロセッサを示しているのではなく、いくつかの重要な節目に焦点を当てている。
Figure 5.16

attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license · CC BY 4.0 · Source出典

Figure 5.16 x86 is a CISC ISA with backward compatibility dating back to the 70s. (attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license)
図5.16 x86はCISCのISAで、1970年代にまでさかのぼる後方互換性を持っている。(出典:著作権 Rice University、OpenStax。CC BY 4.0ライセンス)
First, as technology evolves and the need for faster processing power arises, we move from 16, to 32, to 64-bit processors. This number relates to the size of the registers (fast storage entities inside the processor), the width of the buses (parallel wires connecting the processor to memory), and the amount of memory the processor can access (for n-bit machines, the processor can access 2n bytes of memory). The ISA also evolves in parallel to incorporate the larger registers (hence the move from IA32 to x86-64) and the computations with larger numbers. Second, we can see the tremendous increase in transistors in each generation. Having more transistors means more features implemented inside the processor and hence higher performance and potentially richer ISA.
英語のヒント
第一に、技術の進化とともに、より高速な処理能力の必要性が生じ、プロセッサは16ビットから32ビット、そして64ビットへと移行する。この数は、レジスタ(プロセッサ内部の高速な記憶装置)の大きさ、バス(プロセッサとメモリを結ぶ並列配線)の幅、アクセスできるメモリ量に関係する。nビットの機械では、プロセッサは2nバイトのメモリにアクセスできる。ISAも並行して進化し、大きなレジスタ(そのためIA32からx86-64へ移行した)と、大きな数の計算に対応する。第二に、各世代でトランジスタ数が大幅に増えていることがわかる。トランジスタが増えれば、プロセッサ内部に実装できる機能が増え、その結果、性能が高まり、ISAも豊かになる可能性がある。
The complex architecture structure that assists in executing operations such as mathematical computations and memory storage is called complex instruction set computer (CISC). This is done by combining many simple instructions into a single complex one. This concept came from something called the semantic gap, which is the difference between the HLL program and its assembly equivalent. It is good for programmers to understand assembly language as this skill will help you code in any language. However, assembly programming is so much different from HLL programming that most programmers have difficulty understanding it. The wider the difference, the wider the semantic gap. To reduce this gap and make assembly language more accessible to programmers, x86 was designed to make its instructions a bit more complicated because statements in HLL are complicated. Complicated means a single assembly instruction can do several things. For example, an instruction like addw %rax, (%rbx) means access the memory at a specific address, get the data stored there, add that data to a number, and store that number in a specific place. So, it is accessing the memory, making an addition, and storing the result somewhere. Because the instructions are complicated, this set of these instructions is called CISC.
英語のヒント
数学的な計算やメモリへの保存などの操作の実行を助ける、複雑なアーキテクチャー構造を、複雑命令セットコンピューター(CISC)という。多くの単純な命令を、一つの複雑な命令にまとめて実現する。この概念は、意味の隔たりを表す「セマンティックギャップ」から生まれた。これは、HLLのプログラムと、それに等価なアセンブリプログラムの違いである。アセンブリ言語を理解すれば、どんな言語でコードを書く場合にも役立つため、プログラマーにとって有益である。しかし、アセンブリのプログラミングはHLLとあまりに異なるため、多くのプログラマーが理解に苦労する。違いが大きいほど、セマンティックギャップも広がる。この隔たりを減らし、プログラマーにとってアセンブリ言語を理解しやすくするため、x86では命令を少し複雑にする設計が採られた。HLLの文が複雑だからである。「複雑」とは、アセンブリの一つの命令で複数のことができるという意味である。たとえば、addw %rax, (%rbx)という命令は、あるアドレスのメモリにアクセスし、保存されているデータを取り出し、それをある数に足して、その数を所定の場所に保存することを意味する。つまり、メモリへのアクセス、加算、結果の保存を行っている。命令が複雑なので、こうした命令の集合をCISCと呼ぶのだ。
Complex instructions such as the ones corresponding to a for-loop in HLL were the norm until the 1980s when another viewpoint came into existence that said that complex instructions make the processor slow. Moving into the 1990s, and the appearance of portable devices with their sensitivity to power consumption and battery life, another disadvantage of CISC arose: complex instructions make the processor not only slow, but also power hungry. And, thus, the other viewpoint of simpler instructions called reduced instruction set computer (RISC) came to be the norm. Right now, all the processor families in the world are RISC except x86.
英語のヒント
1980年代までは、HLLのforループに対応するような複雑な命令が普通だった。ところが1980年代には、複雑な命令はプロセッサを遅くする、という別の考え方が現れた。1990年代になり、消費電力と電池の持ちが重要な携帯機器が登場すると、CISCの別の欠点が浮かび上がった。複雑な命令は、プロセッサを遅くするだけでなく、電力も大量に消費させるのだ。そこで、命令を単純にする、縮小命令セットコンピューター(RISC)というもう一つの考え方が主流になった。現在、世界のすべてのプロセッサファミリーは、x86を除いてRISCである。