ex) ANDI 명령어는 ADD에 I를 붙임으로써 기존 명령어와 형식도 다르고 opcode도 다르다는 것을 상기시킨다. (두 명령어는 수치 피연산자를 사용한다는 점에 있어서 다르다) Show - 각 명령어를 이진수로 바꾸기 위해서는 레이블(명령어)에 해당하는 주소를 모두 알아야 한다. - 사용되는 심벌과 주소를 심벌 테이블(symbol table)에서 찾는다. => 심벌 테이블은 알려진 전역변수나 함수의 주소값을 해시 테이블로 저장한다. 3. 링커- 따로따로 어셈블된 기계어 프로그램을 하나로 연결해주고, 실행 파일을 생성한다. - 각 루틴마다 컴파일 하는것이 아니라서 더 빠르다. - 동작 a) 코드와 데이터 모듈을 메모리에 심벌 형태로 올려놓는다. b) 데이터와 명령어 레이블의 주소를 결정한다. c) 외부 및 내부 참조를 해결한다. - 주소를 결정한다는 점에 있어서 에디터와 같은 역할을 해서 링크 에디터라고도 부른다. 4. 로더- 실행 프로그램을 메인 메모리에 적재해서 실행할 수 있게 해준다. - UNIX 동작과정 a) 실행 파일 헤더를 읽어서 텍스트와 데이터 세그먼트의 크기를 알아낸다. b) 텍스트와 데이터가 들어갈 만한 주소 공간을 확보한다. c) 실행 파일의 명령어와 데이터를 메모리에 복사한다. d) 메인 프로그램에 전달해야 할 인수가 있으면 스택에 복사한다. e) 레지스터를 초기화하고 스택 포인터는 사용 가능한 첫 주소를 가리키게 한다. f) start-up 루틴으로 분기해서 인수를 인수 레지스터에 넣고 메인 루틴을 호출한다. 메인 추틴이 끝나고 start-up 루틴(기동루틴)으로 복귀하면 exit 시스템 호출을 사용하여 프로그램을 종료시킨다. 요즘은 프로그램을 소스 코드로 작성한다. 소스 코드는 인간이 이해할 수 있는 언어로 작성한 코드이다. 시스템은 소스 코드를 이해할 수 없다. 시스템은 기계어만 이해할 수 있다. 따라서 누군가 소스 코드를 기계어로 번역해주어야 한다. (C언어의 경우) 컴파일러와 어셈블러가 번역 과정을 맡는다. 먼저 컴파일러가 소스 코드를 어셈블리어로 번역해놓고 나면, 어셈블러가 어셈블리어를 기계어로 번역한다. 소스 코드를 한 번에 기계어로 번역해주지 않고 왜 굳이 두 단계로 나누었을까라는 의문이 들었다. 하지만 만들어진 순서를 생각해보면 당연한 결과인 것 같다. 프로그래밍 언어의 시작부터 사람이 이해할 수 있는 언어가 있었던 것이 아니라, 처음엔 기계어에서부터 시작했다. 기계어는 0과 1로만 이루어져 있기 때문에 너무 불편해서 어셈블리어라는 것을 만들었다. https://www.hex-rays.com/blog/reading-assembly-code/예를 들어 두 숫자를 더하기 위해 0000000F를 이진수로 입력했어야 했는데 어셈블리어를 만들어 'add'라는 명시적인 명령어가 덧셈을 맡도록 하고, 어셈블러가 어셈블리어의 'add' 명령어를 기계어 0000000F로 번역하도록 만든 것이다. 기계어로 프로그래밍을 했던 사람들은 어셈블러와 어셈블리어의 탄생에 매우 기뻤을 것이다. 하지만 어셈블리어만으로 프로그램을 개발하기에 충분하지 않았다. 더 추상화된, 더 고급 수준의 명령과 문법이 필요했던 것이다. 그래서 C와 같이 사람이 이해하기 쉽고 작성하기 쉬운 프로그래밍 언어가 탄생한 것이다. 마치 어셈블리어를 어셈블러가 기계어로 번역해주었듯, 고급 언어도 누군가 어셈블리어로 번역해주어야 했는데 그 역할을 컴파일러가 맡았다고 생각하면 된다. 이를 정리해보면, 사람이 작성한 코드를 기계가 실행하기까지 다음과 같은 변화를 겪는다. 소스 코드 작성 → 어셈블리어로 번역 (by compiler) → 기계어로 번역 (by assembler) 컴파일 시스템지금까지는 언어만 생각했다. 실제로 프로그램을 실행할 때는 언어만 생각해서는 안된다. 필요한 과정이 몇 개 더 있다. (예를 들어, 프로그램에서 printf라는 라이브러리 함수를 사용한다면 이 라이브러리 함수를 가져오는 과정이 필요할 것이다. 프로그램이 실행되는 과정은 사람이 작성한 언어를 기계가 이해할 수 있는 언어로 번역하는 과정 이외에 이런 추가적인 과정도 고려해야 한다.) 프로그램이 실행되는 과정에 참여하는 친구들을 컴파일 시스템이라 부르며 컴파일 시스템에는 다음의 4가지가 있다.
컴파일러(컴파일 단계): 소스 코드를 어셈블리어로 번역. 어셈블러(어셈블리 단계): 어셈블리어를 기계어로 번역한 뒤 재배치가능 목적프로그램 형태로 묶어 목적파일 생성. 링커(링크 단계): 프로그램에서 사용한 다른 목적파일을 통합. 예를 들어 표준 C 라이브러리의 printf 함수를 사용했다면 이미 컴파일된 별도의 목적파일 printf.o를 링커가 통합(아 그래서 재배치가능 목적프로그램이라고 부르는군). 그 결과를 실행가능 목적파일로 메모리에 적재. 기계어와 어셈블리언어 고급언어 본문gpffh1011 2020. 5. 13. 10:41 <<프로그램의 형태>> 프로그램은 인간이 이해 할 수 있는 고급언어와 기계가 이해 할 수 있는 기계어의 번역(컴파일)을 통해 만들어 진다. @고급언어
▼ ▽ 컴파일러 ▼ @어셈블리어(assembly language)
▼ ▽ 어셈블러 ▼ @기계어
-추가- @High Level Language
@ Low Level Language
수학 (공업수학 · 해석학 · 이산수학 · 수리논리학 · 선형대수학 · 미적분학 · 대수학 (환론 · 범주론) · 정수론) · 이론 컴퓨터 과학 · 암호학 · 전자공학 · 언어학 (형태론 · 통사론 · 의미론 · 화용론 · 음운론) · 인지과학 하드웨어 구성 SoC · CPU · GPU(그래픽 카드 · GPGPU) · ROM · RAM · SSD · HDD · 참조: 틀:컴퓨터 부품 기술 기계어 · 어셈블리어 · C(C++ · C#) · Java · Python · BIOS · 절차적 프로그래밍 · 객체 지향 프로그래밍(디자인 패턴) · 해킹 · ROT13 · OTP · IoT · 와이파이 · GPS · 임베디드 · 인공신경망 · OpenGL · EXIF · 마이크로아키텍처 · ACPI · UEFI · NERF · gRPC · 리버스 엔지니어링 · HCI · UI · UX · 대역폭 · DBMS · NoSQL · 해시(SHA · 브루트 포스 · 레인보우 테이블 · salt · 암호화폐) · RSA 암호화 연구및 기타 문서 논리 회로(보수기 · 가산기 · 불 대수 · 플립플롭) · 정보이론 · 임베디드 시스템 · 디자인 패턴 · 데이터베이스 · 프로그래밍 언어{컴파일러(어셈블러 · JIT) · 인터프리터 · 유형 이론} · 메타데이터 · 기계학습 · 빅데이터 · 폰노이만 구조 · 양자컴퓨터 · 행위자 모델 · 인코딩(유니코드 · MBCS) · 네트워크 · 컴퓨터 보안 · OCR · 슈퍼컴퓨터 · 튜링 머신 · FPGA · 딥러닝 · 컴퓨터 비전 · 컴퓨터 그래픽스 · 인공지능 · 시간 복잡도(최적화) · 소프트웨어 개발 방법론 · 정보처리이론 · 재귀 이론 · 자연 언어 처리(기계 번역 · 음성인식) 1. 개요2. 컴퓨터 이전 ~ 컴퓨터 시대 초창기3. 상세4. 배울 수 있는 방법5. 기계어의 간단한(?)예6. 생산성 6.1. 어셈블리 vs 기계어6.2. 생산성 vs 최적화 7. 여담8. 대중 매체에서1. 개요[편집]機械語 / Machine Code (=Machine Language) 2. 컴퓨터 이전 ~ 컴퓨터 시대 초창기[편집]컴퓨터라는 물건이 나오기도 전에 고트프리트 폰 라이프니츠가 이진법을 고안해 기계어에 대한 이론적 토대를 만들었다. 3. 상세[편집]알기 쉽게 0, 1이라고 표현했지만, 엄밀히 말해서 숫자(데이터)는 아니다. 정보는 결국 물리적으로 저장되는데, 이 상태가 '반응 없음·있음', '낮음·높음', '역방향·정방향', 'OFF·ON', '저전압(GND)·고전압(5V)', '음·양'같이 그냥 있고 없고 정도의 '개념'일 뿐이다. 다만, 인간이 '개념'을 받아들이기 위해서는 문자든 음성신호든 개념을 이해시킬 수단이 필요하기 때문에 그냥 직관적으로 0, 1로 표현한 것뿐이다. 참고로 CD 같이 빛을 이용한 저장매체는 빛이 산란되는 부분이 0, 빛이 반사되는 부분이 1이 되고, 마그네틱 테이프 같이 자성을 이용한 경우에는 음극을 0, 양극을 1이라고 취급한다. 그러니까 2진수 체계가 기계어가 될 수 있어도 2진수에 쓰이는 0, 1이라는 숫자 자체가 기계어가 될 수는 없다는 말. 4. 배울 수 있는 방법[편집]어셈블리어는 기계어를 알파벳으로 변환한 것이므로 어셈블리어를 배우는게 기계어를 배우는 것이다. 어셈블리어로 짠 코드를 기계어로 치환하면 그게 바로 기계어로 짠 코드다.[4] 어셈블리어는 컴퓨터공학과에서 컴퓨터 구조론을 연구하거나 시스템 해킹, 임베디드 시스템 등을 다룰 때 배우게 된다. 아주 기초적인 컴파일러조차 돌아갈 수 없는 수준에서의 코딩이나 컴파일 과정에서 발생할 수 있는 오류 혹은 해킹 기법 등을 배울 때 어셈블리어에 대한 지식이 필요하기 때문. 따라서 아래의 내용은 어셈블리어(=기계어)에 대한 내용이다. 5. 기계어의 간단한(?)예[편집]
이 표현을 MIPS라는 아키텍처의 기계어로 옮기면 다음과 같다.
가독성을 높이기 위해서 보통은 4자리씩 끊어서 16진수로 표현한다. 그래서 그렇게 써보자면 다음과 같다.
보기는 좀 편하지만 그래봤자 여전히 무슨 소린지 알 수 없다.[9] 이걸 빠르게 읽어나갈수 있다면 머리 속에 CPU가 장착된 사람일 것이다. 아래는 앞서 본 기계어 코드를 MIPS 어셈블리로 옮긴 것이다. 한 번 비교해 보자.
다음은 리눅스 환경, x86 아키텍처를 이용한 hello world 코드. 출처(breadbox의 코드)
6. 생산성[편집]6.1. 어셈블리 vs 기계어[편집]실상은 어셈블리어나 기계어나 실행 속도는 똑같다.[10] 하지만 코드를 짜는 시간은 어셈블리어가 기계어보다 훨씬 적게 걸린다. 6.2. 생산성 vs 최적화[편집]현대의 고급언어와 기계어를 쉽게 비유하자면, 현대의 고급 프로그래밍 언어는 포크레인 같은 것이며 기계어는 완벽한 핀셋 같은 수준이다. 포크레인은 작업속도(생산성)는 매우 빠르지만 세세한 작업(최적화)은 하기 힘들고, 핀셋은 작업속도는 매우 느리지만 세세한 작업을 할 수 있다. 7. 여담[편집]훨씬 복잡한 예제들을 보고 싶다면 계산기나 메모장의 실행파일을 텍스트 에디터로 열어보자. 메모장으로 열면 외계어 폭풍(...)[11]에 절로 몸사리 칠 것이다. 심지어는 C 처음 배울 때 만드는 Hello World 예제조차 열어보면 수십 수백 줄은 사뿐히 넘어주신다.[12] 8. 대중 매체에서[편집]헛소리 시리즈의 쿠나기사 토모가 프로그래밍할 때 쓰는 언어가 이 기계어라는 설정이다. 쿠나기사 토모의 PC는 메인보드부터 자작이고 OS도 자작이라[14],기계어로 코딩하는 것도 딱히 이상하지는 않다. 쿠나기사가 사용하는 CPU가 현재 가장 많이 사용되는 x86이나 x86-64와 구조가 같을 거라는 보장 자체가 없기 때문이다. 아키텍처가 다른 CPU + 자작 OS 환경에서 본인이 어셈블리어나 고급언어를 만들어 두지 않았다면 닥치고 기계어로 코딩하는 수밖에 없을 수도 있다. [1] 당연히 operator도 다르고, operand가 2개인 아키텍처도 있고 3개인 아키텍처도 있으며, 어디서부터 어디까지가 operator고 operand인지도 다르고, 애초에 아키텍처가 16비트인지 32비트인지 64비트인지에 따라서 명령어의 비트 길이부터(!) 다르다. 어셈블리어 코드 형태로 보면 뭐 ADD SUB같은 기본적 명령어는 거의 똑같은 형태니 비슷하다고도 생각할 수 있겠지만 비트스트림으로 보면 이건 뭐...[2] 보다 엄밀히 말하자면 이진수 언어로밖에 작동하지 않으므로, 의미가 압축된 고급 언어로 명령을 전달했을 경우 이것을 기계어로 해석하는 과정이 별도로 필요하다. 복잡한 로직을 가진 프로그래밍 언어를 기계어로 해석하려면 어쩔 수 없이 비효율적 과정이 끼어들게 되며, 이것은 작업속도를 저하시키는 이유가 된다. 요즘에는 그나마 컴파일러의 성능이 좋아지면서 속도저하가 눈에 띄지 않을 뿐이다.[3] 단 C언어 컴파일러의 프론트엔드는 이미 있는 걸 쓰고 백엔드의 코드 제네레이터 부분만 만든다. 그 외 렉서, 파서, AST옵티마이저 등은 건드리지 않고 있는 것 그대로 쓴다.[4] 어떻게 치환하는지는 앞서 언급했듯이 CPU마다 다르며 CPU 제조사의 홈페이지의 매뉴얼에 자세하게 서술되어 있으므로 그걸 토대로 치환하면 된다. 말그대로 단순 치환이므로 컴퓨터공학적 지식이 필요한 작업은 아니다.[5] 흔히 '디지털'이라 불리는 기기들에 쓰이는 프로그램을 짜는 것을 말한다. 실생활에서 자주 볼 수 있는 전자레인지, 세탁기, 디지털 시계나 공장에서 흔히 볼 수 있는 스마트 팩토리 시스템 같은 것이 임베디드 개발의 결과물이다.[6] 그나마도 컴퓨팅 기술의 발달로 어셈블리어를 쓸 일은 정말 없어졌다. 어지간한 임베디드 개발도 C언어로 하는 경우가 많다.[7] 당연하게도 에뮬레이터나 버추얼라이저로 수행해야 하는 파일들은 친절하게 어셈블리어 따위로 구성돼 있지 않다.[8] 그렇다고 C, C++이 절대 쉬운건 아니다.....[9] 예로 든 MIPS 아키텍처의 경우는 각각의 2진수 필드들이 깔끔하게 4비트나 8비트로 떨어지지도 않기 때문에(MIPS의 R-type 명령어(가산 계열 명령어)들은 op필드 6비트, rs/rt/rd 필드 5비트, shamt필드 5비트, funct필드 6비트로 구성되어 있다.) 오히려 16진수로 표현하면 뭔 소리인지 더욱 알기 힘들다.[10] Reversing: Secrets of Reverse Engineering 中[11] 다만 이는 기계어를 억지로 UTF-8또는 그밖의 '텍스트용' 인코딩으로 가정하고 보여주기에 한자나 한글 같은 유니코드 할당 비율이 많은 문자나 �로 뒤덮일 뿐이다. 이런 경우는 인코딩 에러일 뿐이며 그냥 동영상이나 이미지 파일을 열어도 비슷하게 보인다. 기계어를 좀더 유의미하게 보고 싶다면 전용 헥스 에디터를 사용하거나 디셈블러를 사용해 어셈블리로 변환해야 한다.[12] 하지만 엄밀히 말하면 실행파일(윈도에선 .exe 파일)은 기계어만으로 되어 있는 게 아니라, PE 이미지라고 해서 운영체제가 램에 올릴 때 참고하는 정보들도 함께 들어있는 파일이다. 이 외에도 여러 이미지 형태가 있다.[13] 참고로 폰 노이만은 영어사전을 통째로 달달 외웠을 정도로 날고기던 인류 역사상 최고의 천재 중 한명이었다.[14] 작중에서는 일단 가상머신을 함께 사용하는 것으로 보인다.[15] Error Correction Code 혹은 Error Correcting Code 데이터속 오류를 검출하는 코드 혹은 그것을 정정까지 할수있는 코드를 말한다. 또한 그 기능이 있는 하드웨어를 의미하기도 한다. |