低水準プログラミング言語

水準プログラミング言語とは、コンピュータの命令セットアーキテクチャ、メモリ、あるいは基盤となる物理ハードウェアからの抽象化がほとんど、あるいは全くないプログラミング言語です。この言語のコマンドや関数は、プロセッサの命令と構造的に類似しています。これらの言語は、プログラマにプログラムメモリと基盤となる機械語命令に対する完全な制御を提供します。この言語と機械語の間の抽象化レベルが低い(したがって「低水準」と呼ばれます)ため、低水準言語は「ハードウェアに近い」と表現されることがあります。

マシンコード

PDP-8/eミニコンピュータのフロントパネル。下部のスイッチ列はマシンコードを切り替えるために使用できます。

機械語は第一世代プログラミング言語[1] [2]に分類され、CPU命令セットアーキテクチャに従って符号化・構造化されたデータ です。命令は、メモリへの値の出し入れ、ブール論理、算術演算、値の比較、フロー制御(分岐やジャンプ)などの操作を伴います。

プログラマーが直接機械語でプログラムすることはほとんどありません。代わりに、アセンブリ言語や高水準プログラミング言語を使用します。[3]機械語で書かれたプログラムはほとんどありませんが、コアダンプやデバッグの経験を通して機械語の読み方を学ぶプログラマーもいます

アセンブリ言語

アセンブリ言語は第二世代プログラミング言語[1] [2]に分類され機械語の上に抽象化レベルを提供します。アセンブリ言語で書かれたプログラムは、特定のアーキテクチャ向けに記述および最適化されているため、移植性がありません。 [3] [4] [5] [6]

アセンブリ言語には意味論や形式仕様がほとんどなく、シンボリックアドレスを含む人間が読めるシンボルを、オペコードアドレス、数値定数、文字列などにマッピングするだけです。通常、1つの機械命令は1行のアセンブリコードで表現され、一般的にニーモニックと呼ばれます。[7]アセンブラは、他のオブジェクトファイルとリンクしたり、単独でロードしたりできるオブジェクトファイルを生成します。ほとんどのアセンブラは、共通の命令シーケンスを生成するためのマクロを提供しています。

TX-0PDP-1のようなコンピュータのコーディングが始まった当初、 MITの ハッカーたちが最初にやったことはアセンブラを書くことでした。[8]

Cプログラミング言語

三世代プログラミング言語であるC言語[ 1] [2]は、高レベルと低レベルの定義によって、高レベルまたは低レベルに分類されることがあります。[9] Cの構文は、アセンブリ言語の構文がプラットフォームに依存しているのに対し、Cの構文はプラットフォームに依存しないため、本質的にアセンブリ言語よりも高レベルです。Cは低レベルのプログラミング(コンピューターのハードウェアに直接アクセスする)をサポートしていますが、Cよりも高レベルと見なされることもある他の言語も、ハードウェアに直接アクセスできます。Cを使用する場合、開発者は、メモリ管理やポインタ演算など、他の言語が抽象化する(高レベルのサポートを提供する)比較的低レベルの側面を処理する必要がある場合があります。ただし、Cはハードウェアアクセス、メモリ管理、ポインタ演算などの詳細を隠す抽象化をエンコードできるため、Cコードベースの少なくとも一部は、他の言語で構築された場合と同じくらい概念的に高レベルになる可能性があります。 C が高級言語に分類されるか低級言語に分類されるかは議論の余地がありますが、C はアセンブリ言語よりも高級 (特に構文的に) であり、いくつかの面では他の多くの言語よりも低級です。

C言語はアーキテクチャに依存しない言語ですが、技術的に難しい場合もあるものの、クロスプラットフォームなコードを書くために使用できます。C言語のクロスプラットフォーム開発を容易にする要素の一つは、 C標準ライブラリです。このライブラリは「システム依存オブジェクトへのインターフェースであり、それ自体は比較的システムに依存しません」[10] 。

比較

以下は、n番目のフィボナッチ数を計算するアルゴリズムのx86-64マシン コードです。値は16 進数表現され、各行は 1 つの命令に対応します。

89 f885以降74 2683 ff 0276 1c89 f9ba 01 00 00 0001 00 00 008日 04 1683 f9 0274 0d89 d6ff c989 c2eb f0b8 01 00 00c3

以下は、 Intel 構文を使用したx86-64 アセンブリ言語で記述された同じアルゴリズムです。x86-64プロセッサのレジスタは名前が付けられ、直接操作されます。 関数 は、x86-64 の System V アプリケーション バイナリ インターフェイスに従ってから 64 ビットの引数をロードし、、、、およびレジスタの値を操作して計算を実行し、終了して を返します。このアセンブリ言語には、値を返すという概念がないことに注意してください。結果は、これも System V アプリケーション バイナリ インターフェイスに従って レジスタに格納された後、命令はスタックの最上位の 64 ビット要素を削除し、次の命令をその場所からフェッチします (その命令は通常、この関数を呼び出した命令の直後の命令です)。関数の結果は に格納されます。x86-64 アセンブリ言語では、関数に値を渡したり、関数から値を返したりするための標準はありません (実際、 には関数の概念がありません)。これらは、特定の命令セットの System V ABI などのアプリケーション バイナリ インターフェイス(ABI)によって定義されます。rdiraxrcxrsirdiraxretrax

fib: mov rax , rdi ; 引数は rdi に格納されているので、rax に入れます。test rdi , rdi ; 引数は 0 ですか? je .return_from_fib ; はい - rax にすでにある 0 を返します。cmp rdi , 2 ; いいえ - 引数を 2 と比較します。jbe .return_1_from_fib ; 2 以下の場合は 1 を返します。mov rcx , rdi ; それ以外の場合は、カウンターとして使用するために rcx に入れます。mov rdx , 1 ; 最初の前の数は 1 から始まるので、rdx に入れます。 mov rsi , 1 ; 2 つ前の数も 1 から始まるので、rsi に入れます。.fib_loop: lea rax , [ rsi + rdx ] ;前の 2 つの数値の合計を rax に格納します。cmp rcx , 2 ;カウンターは 2 ですか? je .return_from_fib ; はい - rax に結果が含まれます。mov rsi , rdx ; いいえ - 1 つ前の数値を 2 つ前の数値にします。dec rcx ; カウンターをデクリメントします。mov rdx , rax ; 現在の数値を 1 つ前の数値にします。jmp .fib_loop ; 続けます。.return_1_from_fib: mov rax , 1 ; 戻り値を 1 に設定します。.return_from_fib: ret ; 戻り                                                               

以下は、C での同じアルゴリズムです。これはアセンブリの例と構造は似ていますが、抽象化には大きな違いがあります。

  • 入力(パラメータn)は、ハードウェア上の記憶場所を指定しない抽象化です。実際には、Cコンパイラは、入力の記憶場所を決定するために、様々な呼び出し規約のいずれかに従います。
  • ローカル変数f_nminus2f_nminus1、 は、f_nハードウェア上の特定の格納場所を指定しない抽象化です。Cコンパイラは、ターゲットアーキテクチャに応じてこれらの変数を実際にどのように格納するかを決定します。
  • return関数は返す値を指定しますが、その値をどのように返すかは指定しません。特定のアーキテクチャ向けのCコンパイラは、値を返すための標準的なメカニズムを実装しています。x86-64アーキテクチャ向けのコンパイラは、通常(ただし常にではありませんが)rax、アセンブリ言語の例のように、レジスタを使用して値を返します(アセンブリ言語の例の作成者は、x86-64規約にSystem Vアプリケーションバイナリインターフェースを使用することを選択しましたが、アセンブリ言語ではこれは必須ではありません)。

これらの抽象化により、C コードは C コンパイラでサポートされている任意のアーキテクチャで変更なしでコンパイル可能になります。一方、上記のアセンブリ コードは x86-64 アーキテクチャを使用するプロセッサでのみ実行されます。

unsigned int fib ( unsigned int n ) { if ( ! n ) { return 0 ; } else if ( n <= 2 ) { return 1 ; } else { unsigned int f_nminus2 , f_nminus1 , f_n ; for ( f_nminus2 = f_nminus1 = 1 , f_n = 0 ; ; -- n ) { f_n = f_nminus2 + f_nminus1 ; if ( n <= 2 ) { return f_n ; } f_nminus2 = f_nminus1 ; f_nminus1 = f_n ; } } }                                                            

高水準言語における低水準プログラミング

PL/SBLISSBCPL、拡張ALGOLNEWP 、Cなどの一部の高水準言語は、低水準プログラミング言語にアクセスできます。そのための1つの方法は、アセンブリコードを高水準言語コードに埋め込むインラインアセンブリです。これらの言語の中には、アーキテクチャ依存のコンパイラ最適化ディレクティブを使用して、コンパイラがターゲットプロセッサアーキテクチャを使用する方法を調整できるものもあります。

GNU Cコンパイラ(GCC) の次のCコードブロックは、インラインアセンブリ機能を示しています。[11]

int src = 1 ; int dst ;     asm ( "mov %1, %0 \n\t " "$1、%0を追加" : "=r" ( dst ) : "r" ( src ));         printf ( "%d \n " , dst ); 

参考文献

  1. ^ abc 「プログラミング言語の世代」GeeksforGeeks . 2017年10月22日. 2024年4月27日閲覧
  2. ^ abc 「世代言語とは何か?」www.computerhope.com . 2024年4月27日閲覧
  3. ^ ab 「3.1: 低レベルプログラムの構造」. Workforce LibreTexts . 2021年3月5日. 2023年4月3日閲覧
  4. ^ 「低水準言語とは何か?」GeeksforGeeks . 2023年11月19日. 2024年4月27日閲覧
  5. ^ “Low Level Language? What You Need to Know | Lenovo US”. www.lenovo.com . 2024年7月24日時点のオリジナルよりアーカイブ。 2024年4月27日閲覧
  6. ^ 「低水準言語 - プログラミング言語とトランスレータの分類 - AQA - GCSEコンピュータサイエンス改訂版 - AQA」BBC Bitesize . 2024年4月27日閲覧
  7. ^ “機械語/アセンブリ言語/高水準言語”. www.cs.mtsu.edu . 2024年12月14日時点のオリジナルよりアーカイブ。 2024年4月27日閲覧
  8. ^ レヴィ、スティーブン (1994).ハッカー:コンピュータ革命の英雄たち. ペンギンブックス. p. 32. ISBN 0-14-100051-1
  9. ^ Jindal, G.; Khurana, P.; Goel, T. (2013年1月). 「C、Objective C、C++プログラミング言語の比較研究」. International Journal of Advanced Trends in Computer Science and Engineering . 2 (1): 203.
  10. ^ Kernighan, B. ; Ritchie, D. (1988). 『プログラミング言語C』第2版. p. 163.
  11. ^ 「Extended Asm (GNU Compiler Collection (GCC) の使用)」. gcc.gnu.org . 2024年4月27日閲覧

参考文献

  • Zhirkov, Igor (2017). 『低水準プログラミング:C、アセンブリ言語、そしてIntel 64アーキテクチャにおけるプログラム実行』 カリフォルニア州: Apress. ISBN 978-1-4842-2402-1
Retrieved from "https://en.wikipedia.org/w/index.php?title=Low-level_programming_language&oldid=1305615053"