E D R , A S I H C RSS

어셈블리어

last modified: 2015-02-12 05:38:01 by Contributors

Contents

1. 개요
2. 장점
3. 단점
4. 사용
5. 여담


1. 개요

프로그래밍 언어의 하나. 기계어와 함께 단 둘뿐인 저급언어에 속한다.

기계어라는 게 인간의 관점에선 컴퓨터가 바로 읽을 수 있다는 것만 빼고나면 장점이랄 게 없는 언어이기 때문에 이를 보완하기 위해 나왔다. 기계어와 명령어가 1:1로 대응되는 단어들로 구성되어 있다. 기계어가 CPU 종류에 따라 다 다르기 때문에 어셈블리어 역시 통일된 규격이 없다. 아키텍처에 따라 다 다르다. 즉, 호환성 제로.

문법은 크게 인텔방식과 AT&T 방식으로 나눠진다. 인텔방식은 가독성이 뛰어나고, AT&T 방식은 가독성은 떨어지나, 인텔방식보다 좀더 많은 정보를 포함하고 있다고 선호하는 사람들도 있다. 사실, 간단한 수준이라면 뭘 쓰건 큰 차이는 없으나, 어셈블리어로 본격적인 코딩을 한다면 AT&T 방식은 절대거부하는 프로그래머도 많다.

오늘날 대부분의 어셈블리어는 인텔방식을 사용하지만, 오픈소스쪽 스탠다드 컴파일러셋에 포함된 GNU 어셈블러(GAS)에서 AT&T 방식을 사용하고 인텔방식은 근래들어 곁가지로 지원하는 정도이기때문에 GNU 컴파일러 툴과의 연동성을 위해서라면 AT&T 방식을 알아두어야 한다.

MS 플랫폼쪽에서는 MASM 을 사용하고, 오픈소스쪽은 NASM, GAS 로 양분되며, 그외에 FASM, TASM 등이 있다.

2. 장점

어셈블리어의 장점이라면 기계어에 비해 읽기가 편하다는 점.

001000 00001 00000 0000000000001010[1] 이라는 기계어를 addi $1, $0, 10[2]으로 단순히 바꾼 것뿐이지만 소리내서 읽을 수 있는 단어가 보이는 등(...) 가독성이 좋아졌다. 또한 프로그래머가 따로 주석[3]을 달을수 있게 되어 저런 외계어들이 뭘 의미하는지 나름대로 설명을 써 놓을수 있으니 프로그래밍을 하기 훨씬 수월해졌다.어셈블리어 이후 대부분의 언어는 주석을 달을 수 있는 기능을 가지게 되었다.

그리고 PC가 고사양화된 21세기에는 부각되지 않지만 1980~90년대에 어셈블리어로 게임을 제작하면 저사양 PC에서도 빠른 그래픽 처리가 가능했다. 당연히 어셈블리어로 게임을 제작하는 미친 괴수들은 몇명 되지 않았는데 그 당시 대만의 소프트스타에서는 어셈블리어로 횡스크롤 슈팅 게임을 제작하기도 했다.

3. 단점

다만 C언어 같은 고급언어에 비하면 단어가 심하게 축약되어 있어(addi는 add immediate[4]의 약자이다.)[5] 읽기에 좀 편하며, 언어 자체에서 제공하는 리소스 관리를 거의 이용할 수 없기 때문에 사용하려면 그 CPU의 구조에 통달해야 된다. 그렇기 때문에 생산성은 매우 떨어져서 사용량은 고급언어들에게 밀려 거의 없다. 사실 과거엔 컴파일러가 그야말로 발적화에 가까웠기때문에[6] 어셈블리어를 이용하여 컴파일 된 코드를 고치거나 아예 어셈블리어로 프로그램을 짜는 등 사용하기는 했었으나 요즘은 PC 성능도 좋고 컴파일러도 좋아서 괜히 어셈블리어로 삽질할 필요는 거의 없다시피하다.[7]

4. 사용

다만 시스템 드라이버라거나 임베디드 계열에서는 쌩쌩하게 현역으로 돌아가고 있다. 드라이버에서는 하드웨어를 제어하는 특성상 클럭과 타이밍을 맞춰야 하므로 타임 크리티컬한 것들이 꽤 많다 보니 어셈블리로 하지 않으면 타이밍을 제대로 맞추기 어려운 것도 제법 되기 때문이고, 임베디드에서는 단가나 보드/칩 크기 문제로 8비트 CPU에 고작 램 몇 킬로바이트 정도만 쓰는 경우도 많기 때문이다. 그래도 임베디드라도 좀 여유가 생기면 생산성이 훨씬 높은 최소 C를 쓰는 경우가 많다.

어셈블리어도 여러가지가 존재하는데, 요즘 나오는 어셈블리어는 꽤 고수준 명령들을 지원하는것들이 많고, 심지어 C 에 가까운 프로그래밍이 가능한것도 있다. 물론, 그만한 고수준 명령을 남발하면, 퍼포먼스도 C 만큼 떨어진다.등가교환 다만, 어셈블리어라는 타이틀을 위해서는 기계어와 1:1 대응이 되어야 하기때문에, 퍼포먼스를 원할경우 의식적으로 그런 고수준 명령들을 배제하고 쓰면 상관이 없다. 이런측면에서 보면 C 보다 고수준 어셈블리어가 나을수도 있지만, 어셈블리어는 결정적으로 명령어셋이 다른 플랫폼간 호환성 문제가 절대 해결이 안되는 치명적 단점이 있다.[8]

그 외에 게임이나 고성능이 필요한 작업에서 마지막 최적화 작업을 할 때 직접 어셈블리어 코드를 이용하기도 한다.[9]

중요한건, 어셈블리어를 사용한다고 꼭 퍼포먼스가 상승하는것은 아니다. 크고 복잡한 프로그램들일수록 이런 경향이 있는데, 간단한 작업만 하기에도 복잡한 어셈블리어로 크고 복잡한걸 만들어야 하는 경우, 버그없이 돌아가게 하는것만 해도 이미 엄청난 일이 돼버리는데, 여기에 일반적인 C 컴파일러가 해주는 최적화를 능가하는 수준의 최적화까지 하기란 웬만한 편집증이 아니고서야 사실 거의 불가능하다. 실제로, 역사가 좀 된 프로그램중에는 과거 어셈블리어로 짰다가 C 컴파일러들이 충분히 발달한 이후, C 언어로 다시 만들고보니 퍼포먼스가 오히려 크게 상승했다는 경우도 종종 있다. 즉, 오늘날 임베디드 프로그래밍이 아닌 꽤 크고 복잡한 어플리케이션 프로그램에서 어셈블리어를 사용한다면 보통 고수준 언어들로 만들어 놓고 퍼포먼스의 보틀넥이 되는 부분만 찾아서 어셈블리어로 최적화 튜닝을 해주는정도. 실제로, 보통 프로그램에서 95% 의 코드는 런타임의 시간의 5% 만 차지한다는 격언이 있다. 즉, 런타임의 95% 를 차지하는 5% 정도의 핵심 코드를 찾아서 최적화를 해주는게 최적화의 핵심. 그렇기에 성능에 거의 혹은 전혀 영향을 안미치는 부분까지도 포함해서 퓨어 어셈으로 바닥부터 만드는건 일종의 바보짓이 된다.[10]

실제 컴퓨터 뿐만 아니라 가상 머신에도 어셈블리어가 사용된다. 자바의 바이트코드와 닷넷 프레임워크의 CLR이 대표적인 가상 머신 어셈블리어. 다만, 가상 머신 어셈블리어는 다양한 자료형을 지원하거나 함수를 지원하는 등, 실제 어셈블리어와는 차이를 보이며, 대개 JIT 컴파일러를 거치거나 인터프리터를 통해 해석된다.

5. 여담

어셈블리어를 기계어로 바꿔주는 프로그램을 어셈블러라고 한다. [11]

존 폰 노이만의 제자가 어셈블리어를 만들자 폰 노이만이 노발대발 했다는 이야기가 있다. 고작 그런 거로 컴퓨터님(…)의 성능을 낭비하려 한다나 뭐라나. 물론 이 당시 컴퓨터의 위상은 집채만한 크기면서 계산능력은 지금 계산기보다 딸리고 비싸기는 오라지게 비싸서[12] 국가 단위로 한두 개 있는 정도여서 인간 프로그래머는 컴퓨터에게 계산할 자료를 드리는 대컴퓨터콘택트용휴머노이드인터페이스에 불과했기 때문에 일어난 일. 물론 폰 노이만은 기계어로 자유자재로 코딩이 가능한 굇수였다는 점도 있다.그냥 그 머리로 직접 계산을 하시지 그러셨어요..라지만 저 인간은 진짜로 웬만한 건 다 암산한 괴수였다. 세월이 지나고 심하게 비효율적인 코드도 하드웨어빨로 씹고 실행하고, 컴퓨터 한 대가 프로그래머 한 달 월급보다 싸진 요즘은 프로그래머의 효율이 훨씬 중요하게 취급된다.

크리스 소이어가 이것을 사용해 트랜스포트 타이쿤롤러코스터 타이쿤 1, 2를 만들었다고 한다. 엄청난 괴수임이 분명하다(…). 그래서 그런지 몰라도 오브젝트가 난무하는 시나리오 후반부에도 음악파일을 가져올때를 제외하고 렉이 거의 존재하지 않을정도로 최적화가 잘 되어있다.[13] 또한 저사양에서도 무난하게 돌아가기 때문에 전세계적으로 많은 사랑을 받을수 있는 이유중의 하나가 되었다. [14]
그 그럼 무겐도?!
슈퍼패미콤의 게임들은 닥치고 어셈블리어로 개발할 수밖에 없었다. 사실 슈퍼패미콤 뿐만 아니라 메가드라이브, 패미콤, MSX 등 8, 16비트 세대에 나온 대부분의 게임은 거의가 다 어셈블리어로 개발되어있다. 몇몇은 자체 언어를 제작하는 등 예외를 두고 있기는 하지만. 당시의 하드웨어 성능으로는 아무래도 어셈블리어로 직접 쓴 코드와 컴파일러가 생성하는 코드의 퍼포먼스 차이가 꽤 컸기 때문이다. 물론 그 이전, 그러니까 아타리 쇼크 이전에는 게임 프로그래밍이 곧 어셈블리어 프로그래밍이고 시스템 프로그래밍이었던 시절인지라 어떤 게임기이든 닥치고 어셈블리어로 작성할 수 밖에 없었다. 그나마 요즘은 컴파일러 성능이 많이 좋아져서 굳이 어셈블리어로 삽질할 필요가 없어졌다.[15]

안철수가 만든 V3백신의 토대인 V1은 어셈블리어로 개발되어있다. 어셈블리어 굇수 2[16]

----
  • [1] MIPS 아키텍처의 기계어
  • [2] 리눅스의 부트로더에도 사용되는 AT&T 어셈블리어 구문이다. MASM 계열은 이것과 약간 다르다. 해석하자면 "0번 레지스터(기억장치)에 들어있는 값에 10을 더해서 1번 레지스터에 넣어라"($1 = $0 + 10) 라는 뜻이다.
  • [3] 프로그래머가 어셈블러 또는 컴파일러에게 인식되지 않게 한 부분
  • [4] '상수'라는 뜻이다. 윗 단락 예시에서 10을 더했듯이 고정된 수를 더할 때 쓰인다. 기억장치에서 숫자를 불러올 필요 없이 바로(immediately) 더할 수 있기 때문에 immediate라는 이름이 붙었다.
  • [5] 물론, C 언어도 만들어질 당시에 에디터의 자동완성 기능같은건 상상할수도 없었기때문에 오늘날 함수명이나 변수 하나가 심하면 한줄씩 차지하는 언어들에 비하면 타수를 줄이기 위하여 strxfrm(string transformation) 이나 fma(fused multiply-add) 등의 라이브러리 함수명처럼 축약형을 애용하는 전통을 따르는편이다.
  • [6] 어느정도로 발적화였냐면, while(1){ ... } 이 for(;;){ ... } 보다 느린 컴파일러가 많았다. 오늘날 컴파일러는 둘다 무한루프인걸 알기때문에 속도가 같지만, 과거 컴파일러의 경우에는 while 문의 경우 루프를 돌때마다 항상 저 1 을 테스트했기때문에 속도가 크게 떨어졌다. 때문에, 연식이 좀 된 프로그래머들의 경우 지금도 습관적으로 while(1) 보다 for(;;) 를 애용하는 경우를 종종 볼 수 있다.
  • [7] 요즘은 괜히 어셈블리어 좀 안다고 깝치다가 컴파일러만도 못한 발적화 코드를 내놓는 경우도 비일비재하다. 오래된 CPU와 달리 명령어 실행 시간이 조건에 따라 달라지기 때문에 사람이 그걸 다 따져가며 작업하기가 그만큼 힘들기 때문이다. 물론 컴파일러로는 절대로 할 수 없는 유형의 최적화도 존재한다.
  • [8] 물론, C 의 호환성도 따지고보면 미신이라고 반박하는 경우도 있는데 그래도 거의 완전히 갈아엎어야 하는것과 부분부분 바꿔주면 되는것의 차이는 크다.
  • [9] 이 경우는 보통 컴파일한 바이너라나 실행코드의 메모리 주소를 포인터로 찍고 기계어로 출력한후 이것을 역어셈블한 결과물을 베이스로 작업한다. 어셈블리어는 기계어와 1:1 대응이 되기때문에 바이너리 ↔ 어셈블리어 양방향 전환이 자유로운편이다.
  • [10] 물론, 해당 프로젝트에 인생을 바칠 각오가 되어있다면 상관없다.
  • [11] 컴파일러는 말그대로 편집, 또는 수집을 한다는 소리이다. 예를 들어, C언어의 컴파일러는 소스 코드를 목적 코드로 바꾸고, 오프젝트 파일로 바꾼후, 여러 컴파일에 필요한 파일을 모은후에 바이너리로 만들어 출력을 한다. 어셈블리를 기계어로 바꾸는 과정에는 그런거 없다. 그러기에 어셈블러와 컴파일러로 나누는 것이다.
  • [12] 그 당시가격으로 50만달러인데 지금 가치로는 6백만달러. 72억원정도이다. 애니악 한대가 그 가격.
  • [13] 물론 아무리 어셈블리어로 짜도 못짜는 사람은 더럽게 렉걸린다.물론 어셈블리어를 다룰줄 아는 사람이면 그만큼 괴수니까 그럴 가능성은 낮지만. 여하튼 크리스 소이어의 실력이 대단하다는걸 알수있다.
  • [14] 트랜스포트 타이쿤은 386DX에서도 돌아간다! 오오 크리스 소이어 오오
  • [15] MS의 매크로 어셈블러와 베이직 인터프리터는 IBM PC와 함께, 그리고 볼랜드의 터보 시리즈 컴파일러가 8비트 컴퓨터용으로 출시됐지만, 당시 컴퓨터책과 잡지에서는 C언어를 저급언어라 부르면서도 어셈블리어 강좌를 연재했고, 개인프로그래머는 변환테이블을 보고 핸드어셈블한 걸 기계어 모니터 프로그램으로 직접 입력하기도 했다. 디버그는 트레이스(TRON, TROFF)를 이용해 레지스터와 포인터, 플래그를 직접 보며 근성으로!
  • [16] http://xcoolcat7.tistory.com/292
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2015-02-12 05:38:01
Processing time 0.0927 sec