저수준 프로그래밍 언어

Low-level programming language

하위 프로그래밍 언어는 프로세서의 명령과 구조적으로 유사한 언어 맵의 명령 또는 함수인 컴퓨터의 명령 집합 아키텍처에서 추상화를 거의 또는 전혀 제공하지 않는 프로그래밍 언어입니다.일반적으로 이것은 기계 코드 또는 어셈블리 언어 중 하나를 나타냅니다.언어와 기계어 사이의 추상성이 낮기 때문에 낮은 수준의 언어는 "하드웨어에 가까운" 것으로 설명될 수 있습니다.저수준 언어로 작성된 프로그램은 특정 유형의 시스템 아키텍처에 최적화되어 있기 때문에 비교적 휴대성이 떨어지는 경향이 있습니다.

저레벨 언어컴파일러나 인터프리터 없이 머신 코드로 변환할 수 있습니다.제2세대 프로그래밍 언어는 어셈블러라고 불리는 심플한 프로세서를 사용하여 생성된 코드를 프로세서 상에서 직접 실행합니다.낮은 수준의 언어로 작성된 프로그램은 적은 메모리 용량으로 매우 빠르게 실행할 수 있습니다.높은 수준의 언어로 된 동등한 프로그램은 효율성이 떨어지고 더 많은 메모리를 사용할 수 있습니다.낮은 수준의 언어는 단순하지만 프로그래머가 기억해야 하는 수많은 기술적 세부 사항 때문에 사용하기 어렵다고 간주됩니다.이에 비해 고급 프로그래밍 언어는 컴퓨터 아키텍처의 실행 시멘틱스를 프로그램 사양에서 분리하여 개발을 단순화합니다.

기계코드

PDP-8/E 미니컴퓨터의 전면 패널.하단의 스위치 행을 사용하여 기계어 프로그램을 전환할 수 있습니다.

기계어는 컴퓨터가 이전 변환 없이 직접 처리할 수 있는 유일한 언어입니다.현재 프로그래머들은 프로그램을 기계어로 직접 쓰는 일은 거의 없습니다. 왜냐하면 프로그래머는 높은 수준의 언어가 자동으로 처리하는 수많은 세부 사항에 주의를 기울여야 하기 때문입니다.또한 명령어마다 숫자 코드를 외우거나 조회해야 하며 수정이 매우 어렵습니다.

진정머신 코드는, 통상, 바이너리인 원시 데이터의 스트림입니다."머신 코드"로 코딩하는 프로그래머는 일반적으로 명령과 데이터를 10진수, 8진수, 16진수 의 읽기 쉬운 형태로 코드화합니다.이 코드는 로더라고 불리는 프로그램에 의해 내부 형식으로 변환되거나 전면 패널에서 컴퓨터 메모리로 전환됩니다.

기계어로 작성된 프로그램은 거의 없지만 프로그래머는 코어 덤프를 사용하거나 전면 패널에서 디버깅을 통해 프로그램을 읽는 데 익숙해집니다.

예: n번째 피보나치 수를 계산하기 위한 32비트 x86 머신코드의 16진수 표현 함수:

8B54408 83FA0077 06B80000 0000C383 FA027706 B8010000 00C353BB 01000000 B9010000 008D0419 83FA0376 078BD989 C14AEBF1 5BC3

어셈블리 언어

2세대 언어는 기계 코드 위에 하나의 추상화 수준을 제공합니다.TX-0이나 PDP-1과 같은 컴퓨터에서 코딩이 시작된 초기에 MIT 해커들은 조립기를 [1]쓰는 것을 가장 먼저 했습니다.어셈블리 언어에는 의미론이나 형식 사양이 거의 없습니다.심볼릭 주소를 포함한 인간이 읽을 수 있는 기호를 opcode, 주소, 숫자 상수, 문자열 등에 매핑하는 것에 불과합니다.일반적으로 하나의 기계 명령은 하나의 어셈블리 코드 라인으로 표시됩니다.어셈블러는 다른 오브젝트파일과 링크할 수 있는 오브젝트파일을 생성하거나 직접 로드합니다.

대부분의 어셈블러는 일반적인 명령 시퀀스를 생성하기 위한 매크로를 제공합니다.

예:위와 같은 Fibonacci 번호 계산기., AT&T 구문을 사용하는 x86-64 어셈블리 언어:

_filename:         움직이다 $1, %eax         xorl %ebx, %ebx .syslog_loop:         cmpl $1, %edi         jbe .delay_done(완료)         움직이다 %eax, %ecx         추가 %ebx, %eax         움직이다 %ecx, %ebx         가라앉다 $1, %edi         jmp .syslog_loop .syslog_done:         리트 

이 코드 예에서는 x86-64 프로세서(레지스터)의 하드웨어 기능에 직접 이름을 붙이고 조작합니다.함수는 시스템 V ABI에 따라 %edi에서 입력을 로드하고 완료될 때까지 EAX, EBXECX 레지스터의 값을 조작하여 계산을 수행합니다.이 어셈블리 언어에서는 값을 반환한다는 개념은 없습니다.결과는 EAX 레지스터에 저장되어 있기 때문에 RET 명령어는 코드 처리를 스택에 저장되어 있는 코드 위치(보통 이 함수를 호출한 명령 직후의 명령)로 이동하기만 하면 됩니다.이 함수가 결과를 EAX에 저장하고 거기서 결과를 취득하는 것은 호출 코드 작성자에게 달려 있습니다.x86-64 어셈블리 언어는 함수에서 값을 반환하는 표준을 부과하지 않습니다(실제로 함수의 개념은 없습니다). 값을 추출할 필요가 있는 경우 프로시저가 반환된 후 상태를 조사하는 것은 호출 코드에 달려 있습니다.

기능을 고급 언어인 C의 동일한 기능과 비교해 보십시오.

서명되어 있지 않다 인트 파이브(서명되어 있지 않다 인트 n) {    한다면 (!n)        돌아가다 0;    또 다른 한다면 (n <=> 2)        돌아가다 1;    또 다른 {        서명되어 있지 않다 인트 a, c;        위해서 (a = c = 1; ; --n) {            c += a;            한다면 (n <=> 2) 돌아가다 c;            a = c - a;        }    } } 

이 코드는 어셈블리 언어의 예시와 구조가 매우 유사하지만 추상화 측면에서 상당한 차이가 있습니다.

  • 입력(매개변수 n)은 하드웨어의 저장 위치를 지정하지 않은 추상화입니다.실제로 C 컴파일러는 가능한 많은 호출 규칙 중 하나를 따라 입력 저장 위치를 결정합니다.
  • 어셈블리 언어 버전은 입력 파라미터를 스택에서 레지스터로 로드하고 루프가 반복될 때마다 레지스터 값이 감소하며 스택 상의 메모리 위치 값은 변경되지 않습니다.C 컴파일러는 이 파라미터를 레지스터에 로드하여 같은 처리를 하거나 값이 저장되는 모든 장소에서 값을 갱신할 수 있습니다.코드 작성자로부터 완전히 숨겨진 구현 결정(C 언어 표준 덕분에 부작용이 없는 결정)을 선택합니다.
  • 로컬 변수 a, b 및 c는 하드웨어의 특정 저장 위치를 지정하지 않은 추상화입니다.C 컴파일러는 타깃아키텍처용으로 실제로 그것들을 저장하는 방법을 결정합니다.
  • return 함수는 반환할 값을 지정하지만 반환 방법을 지정하지는 않습니다.특정 아키텍처의 C 컴파일러는 값을 반환하기 위한 표준 메커니즘을 구현합니다.일반적으로 x86 아키텍처용 컴파일러는 어셈블리 언어 예시와 같이 EAX 레지스터를 사용하여 값을 반환합니다(어셈블리 언어 예제의 작성자는 C 규칙을 복사하도록 선택했지만 어셈블리 언어에는 이것이 필요하지 않습니다).

이러한 추상화를 통해 C 컴파일러가 작성된 아키텍처에서 수정 없이 C 코드를 컴파일할 수 있습니다.x86 어셈블리 언어 코드는 x86 아키텍처에 고유합니다.

고급 언어의 저수준 프로그래밍

1960년대 후반에는 PL/S, BLIS, BCPL, 확장 ALGOL(Burroughs 대형 시스템용) C와 같은 고급 언어에는 낮은 수준의 프로그래밍 기능에 대한 어느 정도 액세스가 포함되었습니다.를 위한 방법 중 하나는 인라인어셈블리입니다어셈블리 코드는 이 기능을 지원하는 고급 언어로 삽입되어 있습니다.이러한 언어 중 일부는 아키텍처에 의존하는 컴파일러 최적화 명령을 사용하여 컴파일러가 타깃 프로세서 아키텍처를 사용하는 방법을 조정할 수도 있습니다.

레퍼런스

  1. ^ Levy, Stephen (1994). Hackers: Heroes of the Computer Revolution. Penguin Books. p. 32. ISBN 0-14-100051-1.