기계어 (r20200302판)

문서 조회수 확인중...

1. 개요
2. 컴퓨터 시대 초창기
3. 상세
4. 배울 수 있는 방법
5. 기계어의 간단한(?) 예
6. 생산성
6.1. 어셈블리 vs 기계어
6.2. 생산성 vs 최적화
7. 여담
8. 픽션


1. 개요


Machine Code
0101 0001 0000 0000 0000 0111
0101 0001 0000 0000 0000 1000
0000 0000
0100 1000
0110 1001
기계어로 "Hi"를 출력하는 프로그램.
프로그래밍 언어의 하나. 인간에게 난해한 프로그래밍 언어지만, 이건 컴퓨터만을 위해 사용되는 언어다.
CPU에게 던져주면 CPU가 바로 해독할 수 있는 유일한 언어다. 쉽게 말해 기계의 언어.
비트단위로 표기하기 때문에 01로만 표현된다. 그 때문에 간단한 연산문도 작성하면 옆으로 길게 늘어져 개떡같은 가독성을 자랑한다.

2. 컴퓨터 시대 초창기


배전반에서 배선을 조작하는 방식으로 입력하고 전구(!)의 켜짐/꺼짐으로 결과를 확인했다. 에니악 문서 참고.
그래서 컴퓨터 시대 초창기에는 이걸 컴퓨터처럼 해독하는 작자들도 많이 있었다.
1980년대까지만 해도 기계어를 직접 입력해서 프로그램을 짜는 것은 이상하지 않았다. 당시에는 잡지에 니모닉과 기계어가 나오는 건 예사고 MS-DOS 팁에 DEBUG 명령어를 써서 16진수를 입력하고 .COM 파일을 직접 작성하는 내용이 올라왔다.

3. 상세


알기 쉽게 0, 1이라고 표현했지만, 엄밀히 말해서 숫자는 아니다. 정보는 결국 물리적으로 저장되는데, 이 상태가 '반응 없음, 있음', '낮음, 높음', '역방향, 정방향', 'off, on', '음, 양'같이 그냥 있고 없고 정도의 '개념'일 뿐이다. 다만, 인간이 '개념'을 받아들이기 위해서는 문자든 음성신호든 개념을 이해시킬 수단이 필요하기 때문에 그냥 직관적으로 0, 1로 표현한 것 뿐이다. 참고로 CD 같이 빛을 이용한 저장매처는 빛은 산란되는 부분이 0, 빛이 반사되는 부분이 1이 되고, 마그네틱 테이프 같이 자성을 이용한 경우에는 음극을 0, 양극을 1이라고 취급한다. 그러니까 2진수 체계가 기계어가 될 수 있어도 2진수에 쓰이는 0, 1이라는 숫자 자체가 기계어가 될 수는 없다는 말.
좀 더 보기 쉽게 16진수로 변환하여 보여주기도 하는데 압도적인 길이가 줄어서 마음에 안정감만 줄 뿐, 거지같은 가독성은 마찬가지이다. 어떤 기계어의 경우 2진수에서 16진수로 가도 오히려 가독성이 떨어지기도 한다. 물론 ASCII나 유니코드로 변환하면 이 거지같은 가독성은 극단을 달린다(…). 그리고 궁극적으로 코드를 던져줘도 "그래서 하고 싶은 말이 뭐냐?"[1]란 반응이 나올 정도로 해독하기가 난해하다.
이와 같이 기계어는 초창기 컴퓨터의 명령어 입력 방법 중 하나였다.
엄밀히 말하면 기계어는 특정한 언어가 아니다. 단지 CPU 또는 MPU 제조사에서 CPU를 만들어 낼 때 해당 CPU에서 사용하는 명령어 집합을 공개하는데, 이것을 '기계어'라고 부를 뿐이다. 때문에 CPU가 변경되면 기계어가 달라진다. 같은 회사의 CPU라도 버전 별로 다른 명령을 포함할 수 있으며 다른 회사라도 같은 명령어 집합을 공유할 수도 있다. (기계어 수준의 호환을 말한다.) 같은 관점에서, 어떠한 소스 코드를 컴파일하여 얻어지는(정확히 말하면 어셈블러에 의해 생성되는) 목적 코드 역시 기계 코드와 완전 동일하지는 않다. 목적 코드와 기계 코드는 둘 다 2진수로 이루어진 바이너리 포맷이라는 점에서는 동일하지만, 목적 코드가 링커에 의해 처리될 때 함수나 헤더 파일 등의 실제 메모리 주소를 코드에 반영하는 과정에서 일부 주소값이 변경되기 때문이다.대체 뭔 소린지 모르겠다.
가독성은 0에 수렴하고 배우기도 힘들고 생산성도 심하게 낮다. 또 CPU 종류, CPU의 아키텍처에 따라서 같은 동작을 수행하는 코드라고 할지라도 완전히 다른 0과 1의 나열이 될 수 있기 때문에 이식성도 거지같다.[2] 간단히 CPU 바꾸면 기존에 작성한 기계어 코드가 안 돌아갈 수도 있다. 아주 기본적인 연산자들은 서로 호환이 되는 편이라서 운이 좋으면 돌아갈 수도 있으나 어지간한 수준의 프로그램들의 경우 호환될 확률이 거의 없다. 이 때문에 CPU를 제작하는 업체에서는 새로운 CPU 아키텍처를 공개하고나면 기계어 코드를 함께 뿌린다. NDS 게임을 에뮬레이터 없이 PC에서 돌릴 수 없는 것과 같은 이치다.
프로그램 작동을 키보드 입력으로 비유하면 사람은 해당 문자를 직접 보고 찾아서 누르는 것이고, 기계어는 해당 문자가 존재하는 장소를 찾아서 입력하는 방식이다.
예를 들어 "A"라는 알파벳을 입력한다고 해보자. 인간이라면 A 글쇠를 찾아서 누르면 된다. 기계어에서는 이것을 "밑에서부터 셋째줄, 왼쪽에서부터 두번째에 있는 글쇠를 누르시오." 라고 표현하는 것이다. 그러나 상식적으로 생각해서, 사람끼리 소통할 때에는 이런 식으로 이야기할 이유가 전혀 없다. 게다가 키보드의 모양이나 키배열이 다르다면 A 글쇠가 동일한 위치에 있으리라는 보장도 없다. 해독이 필요한 언어이자 호환성이 낮은 언어인 이유가 바로 이것이다.
하지만 A를 입력하는 행동이 "밑에서부터 셋째줄, 왼쪽에서부터 두번째에 있는 자판을 누르는" 행동이라는 점에는 변함이 없다. (동일한 키 배치를 가지고 있는 키보드라면 말이다.) 즉 기계어는 어떤 프로그램이 작동할 때 가장 근본적인 것을 표현하는 셈이다. 만약 "A 글쇠를 누르십시오" 정도로 표현해준다면 그것이 어셈블리 쯤 된다고 할 수 있다. 사람이 알기 쉽게 하려면 단어를 통째로 보여주고 "다음의 단어를 입력하시오" 라고 하는 편이 훨씬 빠르기 때문에, 이 정도 레벨까지 구현한 것이 고급 프로그래밍 언어이다. 단어보다 정보량이 많은 문장이나 문단을 빠르게 입력할 수 있도록 하는 것은 컴파일러의 성능에 비유할 수 있다.
인간 입장에서, 정보량이 많을수록 의미를 함축적으로 전달하는 것이 프로그래밍 효율이 오르기 때문에, 일반적으로 프로그래밍은 의미의 압축이 많아지고 추상적 개념이 등장하는 쪽으로 발전한다. 그러나 로봇의 경우에는 압축되어 있는 추상적 언어보다 직설적이고 즉각적인 언어가 훨씬 이해하기 쉽다. 그래서 CPU 입장에서는 C언어 같은 고급 프로그래밍 언어를 통해 코드를 입력받는 것보다 어셈블리어나 이진수 코드(어셈블리어와 일대일로 대응하는 코드)를 입력받는 쪽이 훨씬 빠르고 간단하다.[3]
유니코드아스키 코드 같은 코드와는 또 다르다. 이런 코드는 '이 수는 이 문자에 대응한다'하는 약속을 정해놓은 것이다. 컴퓨터는 수(數)만을 다룬다는 사실을 기억하자.
매트릭스에서처럼 영상에서 뭔가 디지털스러움(?)[4]을 어필하고 싶을 때 배경에 촤르륵 하며 흘려보내는데 쓰이긴 한다.
이 문제를 커버하기 위해서 등장한 것이 어셈블리어. 어셈블리어의 경우에는 모든 기계어 코드와 1:1로 대응되는 형태로 되어있다. 문제는 어셈블리어도 상당히 난해하고 생산성이 떨어지다보니 점점 사람이 보고 이해하기 쉽고, 생산성이 높은 프로그래밍 언어들이 개발되기 시작하였다. 생산성이 높다는 의미는 추상화 수준이 올라간다는 의미이고 더 쉽게 풀어쓰면 한 줄의 코드가 함축하는 의미가 늘어난다는 의미이다. 현대 프로그래밍 언어는 한 줄의 코드가 수천만개 이상의 기계어 코드에 대응하기도 한다. 즉 소스 코드의 크기는 10바이트 정도이지만 그것을 컴파일한 실행 바이너리의 크기가 메가바이트 이상의 크기가 된다.
리누스 토발즈가 처음 리눅스 커널을 만들 때 부트 블록에 해당하는 첫 512바이트는 어셈블리어로 코딩했다. 어셈블리어와 기계어는 1:1 관계에 있기 때문에 조금만 더 저수준으로 코딩하려 했다면 기계어를 썼을 수도 있다. 현실에서도 FPGA로 DSP(디지털 신호처리기)를 제작하는 사람은 그 칩의 프로토타입 초기형까지는 테스트 프로그램의 코딩을 기계어로 한다. 기계어로 테스트해서 버그 없고 안정적이다 판단되면 그때서야 어셈블러와 C언어를 개발한다.[5] DSP의 구조가 특이해서 C언어 사용이 불가능할 경우에도 어지간하면 어셈블러까지는 만든다. 어셈블러는 만들기 쉽고(극단적으로 말해서 문자열 치환 로직과 변환표만 있으면 만들 수 있다) 기계어는 코딩하는 본인이 귀찮기 때문.

4. 배울 수 있는 방법


어셈블리어를 배운 뒤 1:1 치환하면 된다. 어셈블리어는 컴퓨터공학과에서 컴퓨터 구조론을 연구하거나 시스템 해킹, 임베디드 시스템 등을 다룰 때 배우게 된다.
어떻게 치환하는지는 해당 CPU 제조사의 홈페이지의 매뉴얼에 자세하게 서술되어 있으므로 그걸 보고 공부하도록 하자. CPU가 제공하는 인스트럭션(기계어 단위) 중 자주 쓰는 인스트럭션 몇십개 정도를 외운다면 아주 불가능한 것은 아니다. (전문적으로 기계어를 가르치는 학교나 학원은 존재하지 않는다.)
대학에서 컴퓨터 전공이라면 컴퓨터 아키텍처에 관해 배울 때 맛만 보는 수준으로 배울 수 있다. 그리고 학교에 시스템 프로그래밍과 관련된 과목이 있으면 상당히 친숙해지게 된다. 시장 영향력이 강한 x86이나 ARM을 주로 다루는 편이다.[6] 물론 16진수로 된 인스트럭션들을 생으로 보진 않고 번역된 어셈블리어를 통하여 공부하게 된다. 어셈블리어와 기계어는 1:1로 대응관계가 있기 때문에 어셈블리어를 공부하는 것만으로도 기계어를 알 수 있고 무엇보다 훨씬 보기 편하기 때문에 일반적인 경우 기계어를 생으로 쓸 일은 없다고 해도 과언이 아니다.
하지만 어셈블리어를 넘어서 순수 기계어 포맷에 대한 지식이 필요한 경우가 전혀 없는 건 아니다. 자신의 코드를 스스로 바꿔서 전염하는 다형성 바이러스를 분석하거나 제작(!)할 때 순수 기계어 포맷에 대한 지식이 필요하긴 하다. 더 접하기 쉬운 예를 들자면 에뮬레이터나 버추얼라이저를 구현하기 위해서도 필요하다. 각각의 아키텍처에 맞는 기계어 코드를 경우의 수에 따라 번역해줘야 하므로[7] 기계어로 모든 걸 코딩할 일은 없다해도 어쨌든 싱싱한 생 기계어를 쓰긴 써야 한다. 이런 것들을 하다보면 C언어가 세상에 존재하는 것은 신의 축복이었단 사실을 깨닫게 된다. 물론 이 생각은 컴파일러를 배울 때 깨진다(…).
또는 당신이 직접 CPU를 설계하면 배울 수 있다. 2019년 현재에는 개발 도구의 발달로 인해 FPGA로 직접 하드웨어를 설계하는 일도 드물지 않게 되었다. FPGA같은 진지한 응용이 아니더라도, 마인크래프트를 하는 게이머들은 레드스톤 논리회로를 사용해 직접 CPU를 설계하기도 한다. 8비트나 16비트 CPU는 양덕들이 맵 파일을 올려놓은 게 있으니 다운받아 돌려볼 수도 있다. 비트 수가 늘어날수록 한 번에 세팅해야 할 레버의 숫자가 8개, 16개, 32개로 늘어나니까 웬만하면 4비트나 8비트 CPU 맵파일을 받자. 간단한 덧셈 동작을 하려고 해도 입력해야 할 인스트럭션 수가 십여 개는 되므로 8비트 CPU조차 100여회의 레버 조작이 필요하다.

5. 기계어의 간단한(?) 예


x = 10 + 2

y = x + 4

이 표현을 MIPS라는 아키텍처의 기계어로 옮기면 다음과 같다.
001001 11101 11101 1111111111111000

001000 00001 00000 0000000000001010

001000 00001 00001 0000000000000010

101011 11101 00001 0000000000000000

001000 00010 00001 0000000000000100

101011 11101 00010 0000000000000100

001001 11101 11101 0000000000001000

어? 토나온다.
가독성을 높이기 위해서 보통은 4자리씩 끊어서 16진수로 표현한다. 그래서 그렇게 써보자면 다음과 같다.
27BDFFF8

2020000A

20210002

AFA10000

20410004

AFA20004

27BD0008

보기는 좀 편하지만 그래봤자 여전히 무슨 소린지 알 수 없다.[8] 이걸 빠르게 읽어나갈수 있다면 머리안에 CPU가 장착된 사람일거다.
다음은 리눅스 환경, x86 아키텍쳐를 이용한 hello world 코드.출처(breadbox의 코드)
7F 45 4C 46 01 01 01 00 00 00 00 00 00 00 00 00 02 00 03 00 01 00 00 00 35 40 B3 04 2C 00 00 00 00 00 00 00 00 00 00 00 34 00 20 00 01 00 00 00 00 00 00 00 00 40 B3 04 B2 0C EB 1C 62 00 00 00 62 00 00 00 05 00 00 00 00 10 00 00 48 65 6C 6C 6F 20 77 6F 72 6C 64 0A B9 4C 40 B3 04 93 CD 80 EB FB


6. 생산성



6.1. 어셈블리 vs 기계어


실상은 어셈블리어나 기계어나 실행 속도는 똑같다.[9] 하지만 코드를 짜는 시간은 어셈블리어가 기계어보다 훨씬 적게 걸린다.
부연설명을 하자면 프로그래밍 언어를 CPU에서 읽고 해독하려면 기계어로 번역해야만 하는데, 어셈블리어는 위에 언급했듯 명령어가 기계어와 1:1 대응된다.
즉, 성능을 위해 기계어로 된 프로그램을 최적화하는 거나 어셈블리어로 된 프로그램을 최적화하는 거나 결국 똑같다는 얘기. 때문에 최적화를 위해 어셈블리어로 코딩하는 일은 간혹 있지만 최적화를 위해 기계어를 쓰는 사람은 이 세상에 존재하지 않는다. 자동차를 끌과 망치로 튜닝하는 사람이 없는 것과 비슷한 이유이다. 수학으로 치자면 온갖 연산자를 냅두고 덧셈만으로 모든 걸 계산하는 것과 비슷하다 사실 CPU도 덧셈만으로 모든 것을 계산한다. 자세한 건 CPU 문서 참고.

6.2. 생산성 vs 최적화


현대의 고급언어와 기계어를 쉽게 비유하자면, 현대의 고급 프로그래밍 언어는 포크레인 같은 것이며 기계어는 완벽한 핀셋 같은 수준이다. 포크레인은 작업속도(생산성)는 매우 빠르지만 세세한 작업(최적화)은 하기 힘들고, 핀셋은 작업속도는 매우 느리지만 세세한 작업을 할 수 있다.
고급언어가 기계어에 비해서 느린 편이긴 하지만, 요즘은 하드웨어 성능이 좋아 단점을 커버하는게 충분히 되기 때문에, 고급언어를 쓰는게 당연하다.
일단 무엇보다도 그냥 딱 보면 알겠지만 타이핑해야 하는 문자의 개수가 어셈블리어나 고급언어 쪽이 훨씬 적다. 거기에 타이핑만 많으면 다행이고, 코딩 시 항상 나오는 불가항력을 고려하면... 안습. 한 마디로 CPU를 직접 제어해야 할 필요성 없이 복잡한 프로그램을 기계어로 짜는 것은 그냥 '잉여짓'이다. 특히 크로스 플랫폼을 고려한다면 CPU 아키텍처 간 이식성이 0인 기계어와 어셈블리어는 고려 대상이 전혀 되지 못한다.
심지어 C언어를 이용해서 프로그램을 짜도 처리속도차이는 기계어와 몇 배 정도밖에 안 난다.[10] NASA 미션 같이 극단적으로 낮은 성능을 커버하기 위해 어셈블리로 쥐어짜야하는 경우를 제외한다면, 같은 시간복잡도라면 컴퓨터 과학에서 몇 배 차이는 크지 않다. 즉 0.003초든 0.006초든 충분히 빠르다.
오히려 0.006초를 0.003초로 만들기 위한 대가가 3주 걸려 만들 것을 3달 걸려 만드는 것이라면 결코 이득이라고 할 수 없다. 게다가 초짜면 컴파일한 결과가 더 빠를 수도 있다. 오히려 3주 걸려 만들 것을 3일만에 만들기 위해 C언어보다 몇십배 느린 고생산성 언어를 쓰는 판국.
7,80년대에는 아직 어셈블리나 기계어를 직접 건드리기도 했는데 이 당시는 개인용 PC의 CPU가 느려터진데다가 컴파일러가 아직 멍청하던 때라 최적화를 하지 않으면 요구 성능을 만족시키지 못 할 정도로 느렸기 때문이다. 예를 들어 게임의 경우 어셈블리어를 동원하지 않으면 플레이에 지장을 줄 정도의 프레임드랍이 일어나거나 심하면 아예 로딩조차 할 수 없었다. 게다가 칩 제조사가 어셈블러를 제공하지 않는 경우도 있어서 이 경우에는 닥치고 기계어를 써야만 했다. 21세기 현대에 70년대 개발 환경을 체험해보고 싶다면 임베디드 프로그래밍쪽을 공부해보면 된다. 다만 임베디드 쪽도 컴파일러만큼은 최신 기술이 적용돼있어 임베디드 개발자도 기계어는 최적화할 때 잠깐 쓰는 정도이다. 물론 상기한 바대로 본인이 직접 칩을 설계했다면(주문형반도체) 본인이 직접 컴파일러를 만들지 않는 이상 기계어를 쓸 수밖에.

7. 여담


훨씬 복잡한 예제들을 보고 싶다면 계산기나 메모장의 실행파일을 텍스트 에디터로 열어보자. 메모장으로 열면 외계어 폭풍에 절로 몸사리 칠 것이다(…). 심지어는 C 처음 배울 때 만드는 HelloWorld 예제조차 열어보면 수십수백줄은 사뿐히 넘어주신다.[11]
폰 노이만은 제자들이 컴파일러와 고급언어를 만들라치면 '이렇게 은혜로운 기계를 가지고 연구는 안 하고 잔머리를 굴린다'고 노발대발 했다고 한다. 본인은 0과 1로만 프로그래밍해서 프로그램을 잘 돌렸다고 한다(...).[12] 심각한 수학빠돌이인 폰 노이만에게 숫자만으로 작동하는 기계어는 일종의 완벽한 그 무엇으로 보였을 것이다. 물론 폰 노이만이 2018년에 재림하더라도 기계어로 Win32 애플리케이션을 짜 보라고 하면 못 할 것이다. 일단 타이핑해야 하는 0과 1의 갯수가 최소 수백만개 이상이다. 언제 다 입력을 마칠지 알 수 없다.
에뮬레이터에서 게임 데이터를 고치는데 쓰이기도 한다(돈 무제한 등). 이 점은 MS-DOS시절 PC-TOOLS등의 어플리케이션으로도 많이 사용하던 방법.

8. 픽션


헛소리 시리즈쿠나기사 토모가 프로그래밍할 때 쓰는 언어가 이 기계어라는 설정이다. 쿠나기사 토모의 PC는 메인보드부터 자작이고 OS도 자작[13]이라, 기계어로 코딩하는 것도 딱히 이상하지는 않다. 쿠나기사가 사용하는 CPU가 현재 가장 많이 사용되는 x86이나 x86-64와 구조가 같을 거라는 보장 자체가 없기 때문이다. 아키텍처가 다른 CPU + 자작 OS 환경에서 본인이 어셈블리어나 고급언어를 만들어 두지 않았다면 닥치고 기계어로 코딩하는 수밖에 없을 수도 있다. 대신 이렇게 만든 시스템 자체의 보안성은 궁극 그 이상이 된다.
Warhammer 40,000의 설정에서 아뎁투스 메카니쿠스테크프리스트들은 Lingua-technis라는 이진 코드로 된 언어를 사용한다고 한다. 쉽게 말하자면 4만년대판 기계어로, 자연어에 존재하는 오류 없이 복잡한 기술 자료를 파일을 보내는 것 처럼 아주 간편하게 통신할 수 있다고 한다. 언어 자체에 ECC[14]가 포함되어있다. 기본적으로 링구아-테크니스를 듣고 말할 수 있게 하는 사이버네틱 이식이 필요한데다가, 외부인이 해독하려 해도 기계교 안에서만 내려져오는 전승을 통해 (2차대전 당시 나바호족 언어 암호마냥) 추가로 암호화가 걸려있어서 아직 문법조차 밖으로 알려지지 않았다고 한다.

[1] 예를들어, 우리는 1+1이라고 하면 2라는 반응을 내놓지만, 컴퓨터는 1+1이라고 입력한다고 해서 별 다른 반응을 내놓지는 않는다. 즉, 실제 프로그래밍은 이렇지 않지만, "1+1을 출력해라" 등으로 말해야지, 단지 식만 내놓는다고 어떠한 명령을 실행하진 않는다는 소리이다.[2] 당연히 operator도 다르고, operand가 2개인 아키텍쳐도 있고 3개인 아키텍쳐도 있으며, 어디서부터 어디까지가 operator고 operand인지도 다르고, 애초에 아키텍처가 16비트인지 32비트인지 64비트인지에 따라서 명령어의 비트 길이부터(!) 다르다. 어셈블리어 코드 형태로 보면 뭐 ADD SUB같은 기본적 명령어는 거의 똑같은 형태니 비슷하다고도 생각할 수 있겠지만 비트스트림으로 보면 이건 뭐...[3] 보다 엄밀히 말하자면 이진수 언어로밖에 작동하지 않으므로, 의미가 압축된 고급 언어로 명령을 전달했을 경우 이것을 기계어로 해석하는 과정이 별도로 필요하다. 복잡한 로직을 가진 프로그래밍 언어를 기계어로 해석하려면 어쩔 수 없이 비효율적 과정이 끼어들게 되며, 이것은 작업속도를 저하시키는 이유가 된다. 요즘에는 그나마 컴파일러의 성능이 좋아지면서 속도저하가 눈에 띄지 않을 뿐이다.[4] 아두이노나 그 다른 디지털과 아날로그의 차이점을 배운 사람은 알고있을 것인데, 디지털은 기계어처럼 오직 0, 1로 신호의 유,무를 나타내지만, 아날로그는 0~225의 값을 나타낸다. 즉, 디지털이 전등을 켜고 끄는 것이라면, 아날로그는 0부터 225까지의 밝기가 있다는 것.[5] 단 C언어 컴파일러의 프론트엔드는 이미 있는 걸 쓰고 백엔드의 코드 제네레이터 부분만 만든다. 그 외 렉서, 파서, AST옵티마이저 등은 건드리지 않고 있는 것 그대로 쓴다.[6] 만약 본인이 컴공 계열이라면 x86쪽에 대해서 배울 가능성이 높고 임베디드 쪽이라면 교수에 따라 갈린다. [7] 당연하게도 에뮬레이터나 버추얼라이저로 수행해야 하는 파일들은 친절하게 어셈블리어 따위로 구성돼 있지 않다.[8] 예로 든 MIPS 아키텍쳐의 경우는 각각의 2진수 필드들이 깔끔하게 4비트나 8비트로 떨어지지도 않기 때문에(MIPS의 R-type 명령어(가산 계열 명령어)들은 op필드 6비트, rs/rt/rd 필드 5비트, shamt필드 5비트, funct필드 6비트로 구성되어 있다.) 오히려 16진수로 표현하면 뭔 소리인지 더욱 알기 힘들다.[9] Reversing: Secrets of Reverse Engineering 中[10] 이것도 이 분야의 전문가일 경우에만. 자신이 컴파일러보다 똑똑할 자신이 없다면 기계어 쪽이 오히려 더 느리다. 현대 CPU의 처리 속도를 극대화 하기 위해서는 파이프라이닝 같은 CPU의 최적화 테크닉이 원활하게 돌아갈 수 있도록 기계어 코드 수준에서 최적화가 되어있어야 한다. 옛날이라면 모를까 2010년대 기준으로 이것을 모두 이해하고 실제 코딩까지 할 수 있는 개발자는 드물다.[11] 하지만 엄밀히 말하면 실행파일(윈도에선 .exe 파일)은 기계어만으로 되어 있는 게 아니라, PE 이미지라고 해서 운영체제가 램에 올릴 때 참고하는 정보들도 함께 들어있는 파일이다. 이 외에도 여러 이미지 형태가 있다.[12] 참고로 폰노이만은 당시 날고 기던 천재 중의 천재였다.[13] 작중에서는 일단 가상머신을 함께 사용하는 것으로 보인다.[14] Error Correction Code 혹은 Error Correcting Code 데이터속 오류를 검출하는 코드 혹은 그것을 정정까지 할수있는 코드를 말한다. 또한 그 기능이 있는 하드웨어를 의미하기도 한다.