전공/시스템 프로그래밍

[시스템 프로그래밍 1강] 어셈블리어란

뜨거운 개발자 2023. 3. 7. 13:25

어셈블리어 소개

어셈블리어를 우리가 공부하는 이유

  • 비전공자와의 차별점 - 컴퓨터 사이언스의 전반적인 지식이 필요하다. 컴퓨터 내부에서 어떻게 작동하는지 아는 것과 모르는 것은 큰 차별점을 선사한다.

기계어란

정의

CPU(컴퓨터 프로세서) 가 이해하는 숫자 언어.

특징

  • 기계어는 2진수로 나타나져 있다.
  • CPU에서 읽는다. 컴퓨터 하드웨어가 이해할 수 있는 유일한 언어이다.
  • 모든 cpu는 cpu에 대응하는 코드가 있다.
    • ex : 01000100 이런식으로 명령을 내리면 무엇을 한다 등, 이런식으로 미리 지정이 되어있다.
  • 명령어는 특정 수의 비트로 구성됩니다.
  • 특정 프로세서에 대한 명령이 8비트인 경우 처음 4비트 부분(opcode)은 컴퓨터에 수행할 작업을 알려주고 두 번째 4비트(피연산자)는 컴퓨터에 사용할 데이터를 알려줍니다.
  • 각 cpu마다 다르다.
  • 우리는 그 중에 x86아키텍쳐를 따르고 모든 x86 프로세서는 공통 기계어를 이해한다.

어셈블리어란

정의

사람이 쉽게 알아들을 수 있게 언어로 기계어를 변경해둔 것.
어셈블러 : 어셈블리 랭귀지를 기계어로 바꿔주는 것.

특징

  • 기계어와 어셈블리어는 1대1 대응이다.
  • 우리가 C와 C++코드를 짜는 경우에 이걸 컴파일러가 기계어로 변경해준다.
  • 기계어는 어셈블리어와 1대1대응이므로 기계어가 만들어지고 그 기계어가 어셈블리어로 번역된다.
  • 어셈블리어는 이식성이 없다.(유지보수 및 배포에서 큰 단점) : 왜냐면 어셈블리어는 특정 프로세서 제품군 용으로 설계되었기 때문이다.

어셈블리이어 장점을 가지는 분야

  • 인베디드 프로그램 작성 : 경제적인 메모리 사용 가능하기 때문에.
  • 실시간 애플리케이션 작성(군사적 목적에 사용) : 시뮬레이션 및 하드웨어 모니터링을 다루는 실시간 애플리케이션에는 아주 정확한 타이밍과 시간 그리고 응답이 필요하기 때문.
  • 고급 언어 프로그래머는 컴파일러가 기계어를 만드는 방식을 사용해서 정확하게 기계어 코드 제어가 힘들지만, 어셈블리어를 사용하면 프로그램 실행 코드를 정확하게 지정이 가능하다.
  • 콘솔 게임 제작 : 콘솔게임은 스펙이 정해져 있기 때문에 그 스펙에 맞게 자원을 사용해야 해서 사용을 한다. 하드웨어적 한계극복을 위해 빠른 실행과 최적화가 필요하다.
  • 하드웨어 디바이스 드라이버 : 어셈블리어가 하드웨어의 명령을 그대로 사용가능하다.
  • low level에서 컴퓨터가 어떤일을 하는지 알 수가 있다.(우리가 공부하는 이유) : 시스템 레벨에서 어떤 일이 일어나는지 안다면 스스로 코드를 더 효율적으로 짤 수가 있다.

어셈블리어 문법 예시

  • 세미콜론 뒤에는 주석이다.
  • 이 내용은 나중 게시물에서 각 명령어에 대해 더 자세히 다룹니다. 여기서는 이런게 있다..! 정도로만 읽어둡시다
  • 역시 레지스터도 뒤에서 다룹니다. 소개 정도로 알고 갑시다.

mov

대입 연산하는 명령어

eax

Cpu안에 메모리를 레지스터라고 부르는 메모리가 있는데, 메모리는 계층 구조를 가지고 있다. 가장 중심에 가까울 수록 속도가 빠르고 작고, 비싸다. 중심에서 멀수록 싸고, 느리고 크기가 크다.
(레지스터→캐쉬→Ram→SSD,HD)
하나당 64비트(수업에서 다루는건 32비트) 인 녀석들이 많지 않고 10개 정도 존재한다.
여러개의 레지스터가 있는데 EAX, EBX ..ECX이렇게 여러개의 레지스터가 있다.

imul ebx

eax를 ebx를 이용해서 곱한다는 의미. imul 명령어를 조금 더 자세히 살펴보자.

imul

  • 음수를 포함한 수를 곱할때 필요한 명령어
  • eax와의 연산만이 아닌 레지스터끼리의 곱, eax가아닌 다른 레지스터와 메모리의 곱, 상수와의 곱을 가능하게한다.

imul source eax와의 곱셈, 레지스터와 메모리만 올 수 있다.

imul register, source두개의 operand를 가진다. add의 형식과 같이 곱한값이 operand1로 대입된다.
imul register, source, immediate두개의 operand와 immediate 즉 상수를 가진다.

cpp코드

int Y;
int X=(Y+4) *3;

어셈블리 코드

mov eax,Y ;Y를 EAX레지스터에 집어넣는다.
add eax,4 ;4를 EAX레지스터에 더한다.
mov ebx,3 ;EBX에 3을 넣는다.
imul ebx ; eax를 ebx를 이용해서 곱한다.
mov X,eax ;eax를 X로 이동시킨다.

이전 기계어와 어셈블리어는 1대1 대응이었다.
이걸 보면 당연하게도 cpp코드와 어셈블리 코드는 1대1대응이 아니라 1대 다 대응을 하게 된다.

어셈블리어의 역사

프로그래밍 초창기

  • 대부분의 애플리케이션은 어셈블리 언어
  • 작은 메모리와 느린 프로세서로 작성됨.

현대 프로그래밍

  • 메모리 크기 커졌다.
  • 프로세서 속도가 증가했다.
  • 프로그램 복잡해졌다.
  • OOP언어가 인기가 많아졌다.

현대 어셈블리어 사용

  • 대부분 프로그램을 어셈블리어로 완전히 작성하기 힘들어졌다.
  • 작성 및 유지보수에 너무 많은 시간을 써야하기 때문이다.
  • 대신, 어셈블리 언어는 속도를 위해 응용 프로그램의 특정 섹션을 최적화하는 데 사용된다.
  • 속도를 최적화하고 컴퓨터 하드웨어에 액세스하기 위해 사용된다.
  • 대부분의 C 및 C++ 컴파일러는 코드에 어셈블리 언어 문을 포함시켜 하드웨어 세부 정보에 대한 액세스를 제공합니다.

마무리 질문

어셈블리어는 이식가능한가?

이식 가능하지 않다!! Cpu가 다르면 각자 다른 기계어가 있다. 따라서 어셈블리어는 다른 cpu에서는 사용 할 수 없다.

AMD64용 어셈블리어는 AMD64 아키텍쳐의 cpu에 이식 가능한가?

같은 아키텍처의 CPU들은 동일한 (기계어)명령어셋을 공유하므로, 어셈블리어도 공유한다고 볼 수 있습니다. 이 경우, 어차피 동일 명령어셋을 사용하므로 사실상 '이식'이 필요없는 상황이다.

CPU의 세대 변화마다 아키텍처와 명령어셋이 달라지는가? 이전의 인텔 맥북은 같은 아키텍쳐와 명령어 집합을 사용하는가?

컴퓨터 사양을 업그레이드하기 위해 CPU를 새로운 세대의 것으로 교체하는 상황을 가정해보죠. 만약, 세대마다 명령어셋이 달라진다면, 우리는 OS는 물론이거니와 컴퓨터에 깔아뒀던 기존 프로그램들을 모두 포기해야 합니다. 기존의 프로그램들이 내리던 명령(기계어)은 더이상 새 CPU에게 통하지 않을테니까요. 이렇게 된다면 사용자가 CPU를 교체하지 않으려 할테니, CPU 제조사에게는 명령어 호환성이 무척 중요하겠죠. 32비트에서 64비트로의 전환이 이뤄지던 시기에 실제로 이러한 일들이 일어났습니다.

같은 어셈블리어는 같은 기계어가 나오는가

같은 어셈블리어 코드는 같은 기계어 코드로 변환됩니다. 어셈블리어는 기계어와 1:1 대응되는 언어로, 어셈블리어 코드는 컴퓨터가 이해할 수 있는 기계어로 변환되어 실행됩니다. 따라서 같은 어셈블리어 코드는 항상 같은 기계어 코드로 변환되어 실행됩니다.
그러나 다른 컴퓨터 아키텍처에서는 동일한 어셈블리어 코드가 다른 기계어 코드로 변환될 수 있습니다. 이는 컴퓨터 아키텍처에 따라 명령어 집합이 다르기 때문입니다. 예를 들어 x86 아키텍처와 ARM 아키텍처에서는 같은 어셈블리어 코드가 서로 다른 기계어 코드로 변환됩니다.

728x90
반응형