바이너리 / 헥스에서 어셈블리 명령어 세트로 정확히 어떻게 이동합니까?


13

그래서 나는 최근에 약간의 임베디드 / 어셈블리 프로그래밍을 배우려고 노력했지만 가장 낮은 수준 (게이트 등)을 배우려고 노력했습니다.

한 가지가 나를 당혹스럽게한다.… 우리가 어떻게 명령 세트를 "얻는가"이다. 나는 게이트 / TTL과 그 작동 방식을 다소 이해하지만 어떻게 우리가 mov, add, clr 등으로 얻는 지 알지 못합니까?

아마도 어리석은 질문 일 것입니다 ....하지만 나는 첫 번째 마이크로 프로세서 / 컨트롤러로 되돌아 가서 생각합니다 ... 어떻게 명령 세트를 디자인하고 작동 시켰습니까?

편집 : Clarity는 첫 번째 마이크로 프로세서에 대해 이야기하는 척합니다. 바이너리에서 실제로 명령어 세트를 만드는 방법은 무엇입니까?


2
모든 명령어에는 값이 있으며 컴파일러는 코드의 구조에 따라 코드를 이러한 명령어로 변환합니다.
Ramhound

1
귀하의 질문을 완벽하게 이해하고 있는지 잘 모르겠지만 여기 , 여기 또는 여기 에서 귀하의 답변을 찾을 수 있다고 생각합니다 .
e-MEE


3
바이너리에서 실제로 명령어 세트를 만드는 방법은 무엇입니까? 사실, "그들"은 그렇지 않았습니다. 적어도 일반적으로 다른 방법입니다. CPU 디자이너는 CPU가 수행 할 작업을 결정한 다음 그로부터 명령어 세트를 만든 다음 명령어 (니모닉)를 opcode (이진 머신 코드)에 매핑합니다. @Scott Whitlock은 아래에 좋은 대답을 제공했습니다. 최소한의 경험에 따르면 귀하의 가정은 거꾸로 있기 때문에 귀하의 질문의 마지막 부분을 다루고 싶었습니다.
Radian

1
이 정말 좋은 책 : www1.idc.ac.il/tecs 는 저 에게이 모든 것을 설명해주었습니다. 대부분의 챕터는 온라인에서 무료로 제공됩니다. 낸드 게이트 (Nand Gate), 어셈블러 (Asembler), 컴파일러 (Compiler)에서 자체 칩 (간단한 하드웨어 설명 언어)을 디자인 한 다음 생성 한 언어로 OS를 작성하십시오! 놀라운 물건, 그리고 공상 과학 학위가없는 사람으로서 그것은 나를 위해 잘 보냈습니다!
bplus

답변:


18

CPU의 핵심은 ALU 입니다. 미리 정의 된 일련의 이진 숫자 인 MOV와 같은 명령어를 수행하고 0, 1 또는 2 피연산자를 가져 와서 해당 작업을 수행해야합니다. 가장 간단한 명령은 본질적으로 아무것도하지 않는 NOP (no operation) 일 수 있습니다. 또 다른 일반적인 작업은 ADD입니다 (두 값 추가).

ALU는 "레지스터"와 데이터를 읽고 씁니다. CPU 내부의 작은 메모리 위치입니다. 명령어의 일부 (사용중인 레지스터 수에 따라 각 입력에 대해 2 ~ 3 비트)는 읽을 레지스터를 나타냅니다. ALU 외부의 CPU에는 메모리에서 레지스터로 필요한 데이터 (및 명령어)를로드하고 레지스터의 결과를 다시 메모리에 쓰는 것을 처리하는 장치가 있습니다. 결과를 기록 할 위치도 다른 2 또는 3 비트로 인코딩됩니다.

연산을 나타내는 이진수 인 "op code"의 선택은 임의적이지 않습니다. 잘 선택된 opcode는 ALU의 복잡성을 줄입니다. 각 비트 또는 비트 그룹은 ALU에서 특정 논리 게이트를 활성화 및 비활성화하는 경향이 있습니다. 예를 들어, ADD 명령어는 출력 스테이지가 내부 추가 로직의 결과를 선택하도록해야합니다. 마찬가지로, MUL 명령어는 곱셈 논리의 결과를 선택합니다. 설계에 따라 가산기 및 곱하기 회로 모두 실제로 입력 피연산자에 대한 작업을 수행 할 가능성이 높으며 변경되는 출력 선택 (ALU의 출력 비트에 기록되는 것) 일뿐입니다.


1
나는 무엇을 묻는 지 추측합니다. 어떻게 선택합니까? 그리고 그들은 실제로 그것을 할당하는 방법은 무엇입니까?

1
@ Sauron : 세 번째 단락을 다시 읽고 이진 산술 및 디지털 회로를 이해하십시오. 디지털 회로에서 8 비트 라인으로 256 개의 명령으로 명령 세트를 나타낼 수 있습니다. 즉, 가능한 모든 상태를 전송하려면 하드웨어 장치에 8 개의 IO 포트가 필요합니다 (라인 당 2 상태 ^ 8 라인 = 256 가능한 상태). 프로세싱 유닛은 그 디지털 입력 신호로 무엇을할지 결정할 수있다. 디지털 회로는 두 가지 하드웨어 상태 (Hi 및 Lo, 전압 또는 전압 없음)를 의미합니다. 그게 바이너리가 나오는 곳입니다. 이진 표현은 금속에 가장 가까운 표현입니다.
팔콘

3
@Sauron- 디지털 멀티플렉서 를 찾아 디지털 회로가 여러 값 중 하나를 어떻게 선택할 수 있는지 확인하십시오. 8 비트 버스가있는 경우이 바이너리 디지털 멀티플렉서 중 8 개만 병렬로 필요합니다.
Scott Whitlock

1
@ 팔콘 좋아 .... 더 이해가 생각합니다. 결국에는 모든 것이 이진 신호로 내려갑니다. 심지어 "mov"와 같은 명령조차도 여전히 이진으로 표시됩니다.

1
@ Sauron-CPU에 대한 연구를 통해 op 코드가 무엇이며 어떻게 작동하는지 이해하는 데 도움이됩니다. 왜 "왜"라는 질문을하더라도 특정 연산 코드를 선택하는 것이 중요하지 않은 것은 큰 의미가 없습니다. 그것들이 어떻게 선택되는지 이해하면 CPU와 그 구조에 대해 더 잘 이해하는 데 도움이 될 수 있습니다.
Ramhound

9

나는 당신의 질문을 문자 그대로 받아들이고 일반적으로 컴퓨터가 아닌 주로 마이크로 프로세서에 대해 논의 할 것입니다.

모든 컴퓨터에는 일종의 기계 코드가 있습니다. 명령어는 opcode와 하나 이상의 피연산자로 구성됩니다. 예를 들어, Intel 4004 (최초의 마이크로 프로세서)에 대한 ADD 명령어는 1000RRRR로 인코딩되었습니다. 여기서 1000은 ADD의 opcode이고 RRRR은 레지스터 번호 0-15 (2 진수로 0000-1111)를 나타냅니다.

16 개의 4 비트 레지스터 중 하나를 참조하는 다른 모든 명령어 (예 : INC, ISZ, LD, SUB, XCHG)는 하위 4 비트를 사용하여 레지스터 번호를 인코딩하고 상위 4 비트의 다양한 인코딩을 지정합니다. opcode. 예를 들어, ADD, SUB, LD 및 XCHG는 레지스터 필드와 결합 된 opcode 1000, 1001, 1010 및 1011 (모두 이진)을 사용합니다. 따라서 로직을 단순화하기 위해 패턴이 어떻게 사용되는지 확인할 수 있습니다.

최초의 컴퓨터 프로그램은 기계 언어로 프로그램을 만들기 위해 1과 0을 직접 인코딩하여 직접 작성했습니다. 그런 다음 ROM (읽기 전용 메모리)에 프로그래밍되었습니다. 이제 프로그램은 일반적으로 마이크로 컨트롤러의 경우 전기적으로 지울 수있는 플래시 메모리에 작성되거나 마이크로 프로세서 인 경우 RAM이 부족합니다. (후자는 여전히 부팅을 위해 일종의 읽기 전용 메모리가 필요합니다.)

기계 언어는 지루해지기 때문에 니모닉 어셈블러 언어를 사용하여 명령 당 한 줄의 어셈블리 코드를 기계어 코드로 변환하는 어셈블러 프로그램이 개발되었습니다. 따라서 10000001 대신 ADD R1을 작성합니다.

그러나 첫 번째 어셈블러는 기계 코드로 작성해야했습니다. 그런 다음 자체 어셈블러 코드로 다시 작성할 수 있으며 기계 언어 버전을 사용하여 처음으로 어셈블했습니다. 그 후 프로그램은 스스로 조립할 수 있습니다 (부트 스트랩 핑이라고 함).

첫 번째 마이크로 프로세서는 메인 프레임과 미니 컴퓨터가 오래전부터 개발되었고 4004가 어쨌든 어셈블러를 실행하는 데 적합하지 않았기 때문에 인텔은 아마도 대형 컴퓨터 중 하나에서 실행되는 크로스 어셈블러를 작성하여 어셈블리 코드를 번역했습니다. ROM에 프로그래밍 할 수있는 이진 이미지로 4004.


4

매우 낮은 수준의 컴퓨터는 데이터 경로제어 로 나타낼 수 있습니다 . 이것들을 함께 인터넷 검색하면 디지털 아키텍처 / 디자인의 기초가되기 때문에 많은 책을 읽을 수 있습니다.

나는 요약하기 위해 최선을 다할 것입니다.

여기에 언급 된 바와 같이, ALU의 핵심은 ALU (및 CPU의 다른 부분)에 대해 알아야 할 것은 다른 작업에 대해 재구성 할 수 있다는 것입니다. 보다 구체적으로, 우리는 데이터 경로 를 재구성하는 기능을 가지고 있는데, 이는 매개 변수가 어떻게 인출되는지, 어떤 동작을 수행하는지, 그리고 이후에 저장 될 위치입니다. 이 세 가지를 조작 할 수 있다고 상상해보십시오 . 이것이 우리의 통제 입니다.

우리는 어떻게 이것을 달성합니까? 이미 언급했듯이, 우리는 저수준 디지털 로직을 활용하고 다른 경로에 대한 멀티플렉서를 만들 수 있습니다. 멀티플렉서는 입력 용 비트 세트를 사용하여 제어됩니다.이 비트는 어디에서 가져 옵니까? 지침 자체에서 인코딩되었습니다. 테이크 아웃 : mov, add 등과 같은 명령어는 CPU에 특정 작업에 대한 데이터 경로를 구성하는 방법을 알려주는 일련의 비트입니다. 읽고있는 내용 (mov, add)은 사람이 읽을 수있는 형태 (조립 언어)이며 프로그램은 데이터 경로 및 작업 절차를 정의합니다.

이것이이 분야에서 더 많은 지식을 가진 사람들에게 더 복잡한 과정을 지나치게 단순화 한 것에 대해 사과드립니다. 참고로, 전기 공학 스택 교환은 매우 낮은 수준의 논리를 다루기 때문에이 질문을하기에 좋은 장소입니다.


3

귀하의 질문을 이해하면 bin / hex 또는 assembly가 어떻게 관련되어 있는지 이해할 수 없습니다.

귀하의 질문의 핵심은 기본 게이트 및 AND 또는 OR에서 이동,로드, 저장, 추가 등과 같은 지시 사항을 얻는 방법이 아니라고 가정합니다.

나는 기본 게이트 및 http://github.com/dwelch67/lsasim 과 같은 것들에서 덧셈과 뺄셈이 어떻게 작동하는지에 대한 세부 사항이있는 처음부터 직접 만든 작은 교육 지시 세트를 가지고 있습니다 .

Petzold의 코드 (뭔가) 책을 찾으십시오. 초급으로 갈 수 있지만 컴퓨터와 전자 제품과는 아무런 관련이 없으며 바이너리, 16 진수 및 기본 게이트 등으로 천천히 걸어갑니다.

오늘날 처음부터 새로 구축하는 방법에 대해 묻고 있습니까, 아니면 하루에 어떻게 해냈습니까? 오늘은 명령어 세트의 정의부터 시작하겠습니다. 당신은 앉아서 그것을 작성하고, 당신은 당신이로드해야하고 저장하고 움직여야하고 물건을 가져야하는 명령어의 유형에 대해 생각합니다. 그리고 레지스터의 수, 레지스터의 크기, 이것은 부분적으로 명령어 크기에 영향을 미칩니다. 명령 크기에 대해 ...

프로그램을 어떻게 작성합니까? 텍스트 편집기에서 빈 화면으로 시작 하시겠습니까? 필요한 변수, 함수, 프로그래밍 언어 등을 해결하려는 작업에 대한 아이디어가 있습니다. 각 사람은 다르지만 어느 정도는 (함수 정의 및 작성), 그 중 일부 (재사용 가능한 정의 및 열거 및 구조체 및 항목으로 헤더 파일 만들기) 및 다른 것 (코드, 변수 및 코드로 함수 채우기). 그리고 서로 다른 작업을 순환하면서 결국에는 코드 크기, 속도, 가독성, 품질, 기능 등의 균형이 있다고 생각합니다. 하드웨어 디자인과 다르지 않습니다. 하드웨어 설계자는 프로그래밍 언어 (vhdl, verilog)도 사용하며 동일한 프로세스를 거칩니다.

소프트웨어 프로그램이 등장하는 것과 마찬가지로 욕구, 성능, 크기, 기능 등의 균형을 맞 춥니 다. 원하는 디자인 또는 상사가 만든 디자인 규칙이있을 수 있습니다. 소프트웨어 디자인과 마찬가지로 초기 디자인을 구현할 때 큰 실수가 있고 초기 디자인으로 돌아가서 명령 세트, 크거나 작은 변경을 변경해야 함을 알 수 있습니다. 컴파일 된 코드의 품질, 성능 등을 획기적으로 향상시키는 몇 가지 특정 명령이 실제로 필요한지 확인하기 위해 컴파일러 및 시뮬레이션 된 프로세서가있을 수 있습니다.

그래서 당신은 처음부터 명령어 세트를 발명했습니다. 하드웨어 디자인에 대한 약간의 경험을 사용하여 유사한 비트 패턴으로 유사한 명령어를 그룹화하여 하드웨어 언어 프로그래밍뿐만 아니라 전력 및 게이트를 절약하기 위해 더 쉽게 디코딩 할 수 있습니다. 좋은 물건. 요즘에는 일종의 시뮬레이터를 만들 것입니다. 제 이해는 ARM이 소프트웨어 시뮬레이터였습니다. 하드웨어 디자인은 나중에 나왔지만 사실인지 알지 못하지만 그 이야기를 고수합니다. 이것은 팀에 달려 있습니다. 어떤 팀은 하드웨어 전문가 일 수도 있고 hdl에서 프로그래밍에 들어가기를 원할 수도 있습니다. 나 같은 팀은 둘 다 조금하고 싶을 수도 있습니다. 요즘 좋은 하드웨어 언어 시뮬레이터를 사용할 수 있으므로 하드웨어 시뮬레이션 프로그램 / 패키지를 사용하여 컴파일 및 시뮬레이션 할 하드웨어를 구축 할 필요가 없으며 많은 디버깅 작업을 수행 할 수 있습니다. 소프트웨어 팀은 명령어 세트를위한 어셈블러 및 컴파일러를 개발하고 시뮬레이션 된 램 및 롬 피드 프로그램을 사용하여 시뮬레이션 된 프로세서에 적용 할 수 있습니다. 우리는 오래 전에 일하지 않은 프로세서에서 전체 리눅스 부팅을 시뮬레이트했으며 많은 시간이 걸렸지 만 작동했습니다 (논리에서 캐시 버그를 발견했습니다).

그래서 지금 당신이 정말로 생각하고있는 것에 대해. 명령어 세트가있는 기본 게이트에서 프로세서로 어떻게 이동합니까? 기본 게이트 AND 또는 OR은 실제로 아날로그가 아니며 시간 개념이 없으므로 입력의 전압을 즉시 변경할 수 없으며 전압을 변경하면 출력이 변경되기 시작합니다. 게이트는 트랜지스터로 만들어지고 트랜지스터는 증폭기이며, 입력에 약간의 숫자를 곱하고 다른쪽에 많은 전류가 흐르도록하십시오. 로직 게이트로 사용할 때 실제로 과포화 상태에있는 경우 입력 전압이 너무 높거나 낮아서 트랜지스터가 최대 전압 만 구동하거나 전압 (전류)이 없어야합니다. 기본적으로 송신기는 스위치로 전환됩니다. 간단히 말해 시간 개념은 없습니다. 명령어 세트를 갖기 위해서는 프로그램을 순서대로 진행하기 위해 명령어가 발생하도록해야합니다. 이제 우리는이 명령어에 대한 개념을 가져야합니다. 앰프를 스위치로 전환하는 게임과 마찬가지로 기본 로직 게이트를 시계와 함께 사용하여 유사한 게임을 즐길 수 있습니다. 시계는 일정한 속도로 켜고 끄는 전압을 만드는 캔 (여기에 들어가기에 가치가없는)의 마법 결정에서 나온 것입니다. 논리 방정식에 해당 전압을 사용하면 시퀀스를 시작할 수 있습니다. 시계는 일정한 속도로 켜고 끄는 전압을 만드는 캔 (여기에 들어가기에 가치가없는)의 마법 결정에서 나온 것입니다. 논리 방정식에 해당 전압을 사용하면 시퀀스를 시작할 수 있습니다. 시계는 일정한 속도로 켜고 끄는 전압을 만드는 캔 (여기에 들어가기에 가치가없는)의 마법 결정에서 나온 것입니다. 논리 방정식에 해당 전압을 사용하면 시퀀스를 시작할 수 있습니다.

이 진리표에 대해 아주 간단히 생각해보십시오.

0 0 0
0 1 1
1 0 1
1 1 0

이진으로 :

0 + 0 = 1
0 + 1 = 1
1 + 0 = 1
1 + 1 = 10 (2 decimal)

1 비트 가산기 인 lsbit에만 초점을 맞추고, 위의 진리표는 1 비트 가산기를 설명합니다. XOR 게이트에 대해서도 설명합니다. 하나의 입력은 참이거나 다른 입력이지만 둘다는 아닙니다.

하나 이상의 비트를 얻으려면 캐리 비트 캐리 및 캐리를 살펴보고 3 비트 가산기 두 피연산자와 캐리, 두 개의 출력, 캐리 및 결과 비트가 필요합니다. 3 개의 입력 2 개의 출력 가산기가 있으면 원하는만큼 확장 할 수 있습니다. 그러나 이것은 여전히 ​​아날로그이며 게이트는 즉시 변경됩니다.

이 아날로그 가산기를 ADD 명령어로 바꾸는 방법은 여러분이 배열 한 게이트에 대한 입력으로 앉아있는 명령어를 보는 논리를 가지고 있다는 것입니다. 명령어의 비트 중 일부는 add 명령어이며, 비트 중 일부는 하나의 피연산자가 이러한 레지스터라고 말하고 레지스터 7, 아마도 다른 비트는 다른 피연산자가 레지스터 4라고 말할 수 있으며 아키텍처에 따라 명령에 결과를 레지스터 2에 넣었다는 다른 레지스터가 정의되어있을 수 있습니다. 이제 더 많은 논리는 레지스터 7의 내용을 alu 가산기의 한 입력으로 라우팅하고 4의 입력을 가산기로 라우팅해야한다는 것을 알았습니다. 레지스터 2에 대한 가산기의 출력 클럭이이 로직의 일부이기 때문에 클럭 기간의 시작부터 다음 클럭 기간의 시작까지의 기간이 있습니다. 여기서 모든 아날로그 신호가 정해져 연결되어있는 논리 방정식을 해결합니다. 전등 스위치를 켤 때와 달리 전등 상태를 말하기 끄기에서 켜기로 변경합니다. 그 빛이 예열되고 기본적으로 정상 상태가되는 데 시간이 걸립니다. 여기서 크게 다르지 않습니다.

이 클럭주기가 AND 명령의 실행 단계 인 경우 다음 클럭주기에 결과를 출력 레지스터에 저장하는 것과 같은 논리가 있습니다. 동시에 다음 명령 등을 가져올 것입니다. 따라서 아날로그 로직이 로직 방정식을 빠르게 해결할 수 있기 때문에 alu 실행이 종종 한 클럭주기 인 최신 프로세서의 경우입니다. 오래된 프로세서는 몇 개의 숫자로 계산하여 가산기를 연결 한 상태로두고 가산기 로직이 해결 될 때까지 x 개의 클럭주기를 기다린 다음 출력 결과를 샘플링하고 alu에 다른 입력을 공급하고 x의 클럭주기를 기다립니다. 그것을 해결하기 위해 영원히 또는 전원이 꺼질 때까지 반복하십시오.

논리 방정식은 무엇을 의미합니까? 당신이 원한다면 AND, OR, NOT 게이트의 관점에서 생각할 수 있습니다. alu 가산기 회로에 대한 각 입력 비트에 대해 현재 명령을 포함하는 플립 플롭 (개별 / 단일 메모리 비트)을 포함하는 클럭을 포함하는 매우 긴 방정식이 있습니다. 메모리 비트). 입력 한 작업을 수행 한 다음 결과를 완료하고 반환하는 기능인 경우, 작성한 언어로 작성된 단일 소프트웨어 기능을 사용하십시오. 가능한 모든 입력 조합과 해당 기능을 통해 다른 실행 경로가 무엇인지 생각하십시오. 고급 언어로 작성했을 수도 있지만 해당 언어로도 중첩 된 if-then-else 구조를 사용하여 더 원시적이고 기본으로 다시 작성할 수 있습니다. 어쩌면 어셈블리 언어로 내려갑니다. 내가 말하는 방정식과는 달리, 하드웨어 프로그래머는 선택한 프로그래밍 언어가 너무 많이 절약 할 때 어셈블리 언어로 긴 바람이 불면 if-then-else 트리에서 프로그래밍하는 것보다이 긴 바람 방정식에 프로그래밍하지 않습니다. 사용하는 컴파일러가 많은 if-then-eles를 사용하여 작은 소스 코드를 긴 어셈블리로 변환하는 것처럼 하드웨어 프로그래밍 언어 코드를 가져 와서 논리 방정식으로 변환하는 컴파일러가 있습니다.

이제 첫 번째 CPU로 돌아갑니다 (오늘날 우리는 마이크로 컨트롤러를 고려할 것이지만 CPU였습니다). 위의 모든 내용을 종이로 작성했으며 실제로 논리 방정식을 작성한 하드웨어 프로그래밍 언어를 사용하지 않았지만 게이트 수와 와이어를 간단하게 연결하기 위해 게이트 수와 와이어 수를 만들기 위해 명령에 대한 비트 패턴을 더 신중하게 선택했습니다. 실용적으로. 종이에 손으로 당신은 긴 배선 논리 게이트의 긴 목록을 생성 한 다음 실리콘 마스크의 날려 버린 버전에 실제 구성 요소를 그려야했습니다. 오늘날에도 칩은 일반인의 관점에서 사진이나 실크 스크린과 유사한 공정을 사용하여 수행되므로, 인쇄하고 축소하면 실리콘 층에 적용 할 수 있습니다.

다시 여기에 모든 사람들이 어셈블리를 더 잘 다룰 수 있었으며, 어셈블리 프로그래밍을했을뿐만 아니라 텍스트 편집기 나 어셈블러가 없어서 첫 번째 프로그램을 종이에 직접 써야 할 수도있었습니다. 참조 매뉴얼을 사용하여 수동으로 기계 코드 1과 0으로 변환했습니다. 이러한 컴퓨터 중 일부에서는 스위치를 뒤집어 주소 비트를 뒤집고 종이의 숫자와 일치 할 때까지 데이터 비트를 뒤집고 시계 비트를 뒤집은 다음 아래로 메모리 위치를로드하여 램을로드해야 할 수도 있습니다. 1 바이트의 프로그램 명령어를 수백 번 더 반복하고 실수하지 않기를 바랍니다.

첫 번째로 C 컴파일러가 다른 언어로 작성되었다고 말할 수있는 것과 마찬가지로 C로 다시 작성되고 첫 번째 C 컴파일러에 의해 다시 컴파일되어 자체 호스팅됩니다. 그런 다음 C 컴파일러를 사용하여 자체 프로그래밍이 된 다른 프로그래밍 언어를 발명했습니다. 우리는 스스로 구축 한 운영 체제와 텍스트 편집기를 발명했으며, 커튼 뒤에 숨어있는 몇 명의 사람들에게 남은 것은 모두 검은 마술입니다 ...

그렇습니다. 매우 오래 감았습니다. 그것은 진정으로 이해하기 위해 수년간의 연구와 경험이 필요한 큰 질문입니다. 내 lsasim을보십시오, 나는 아무것도 전문가가 아니라고 주장하지만 명령 세트입니다 .C로 작성된 명령을 실행하는 시뮬레이터와 하드웨어 프로그래밍 언어로 구현 된 프로세서의 다른 구현이 있습니다. 다른 도구를 사용하여 시뮬레이션했습니다. 또한 조잡한 어셈블러 및 기타 도구 등이 있습니다. 아마도이 중 일부, 특히 하드웨어 프로그래밍 언어 코드를 살펴보면 내가 요청한 것과의 차이를 줄일 수있을 것입니다. 그 격차를 좁히지 않았거나 긴 탄젠트 탄젠트를 만들면이 대답을 행복하게 제거 할 것이라고 알려주십시오 (프로그래머 교환에서 많은 시간을 할애 할 수 없다고 가정).


이것은 실제로 저자의 질문에 대답하지 않으며 적어도 토론에 아무것도 추가하지 않으며 수락 된 답변이 다루지 않았습니다. 이진 수학은 100 % 정확하지 않습니다. 1 + 1은 오버플로가 1 인 0입니다. 레지스트리의 크기에 따라 2 또는 0입니다.
Ramhound

@dwelch DAMN! 나는 당신의 다이 하트 팬입니다. +1
AceofSpades

2

CPU는 0과 1에서 작동합니다. 모든 명령어에는이를 정의한 일련의 비트가 있습니다. Thsi는 기계 코드였습니다. 인간이 읽고 쓰는 것이 어렵습니다. 첫 번째 단계로 0과 1을 4 비트 시퀀스로 그룹화하고 0에서 F를 사용하여이를 나타냅니다. 이것은 우리가 기억해야 할 숫자를 줄 였지만, 여전히 지시를위한 16 진 코드를 기억하는 것은 쉽지 않았습니다.

그래서 우리는 MOV 나 ADD와 같은 "단어"를 가진 어셈블리를 사용하기 시작했습니다. 어셈블러는 명령어를 올바른 0 '및 1 세트로 바꾸어 어셈블리 "목록"을 기계 코드로 변환합니다.

결국 우리는 "명령"이 기계 코드의 전체 시퀀스를 나타낼 수있는 "고급"언어를 개발했습니다.


참고로, 8 진수는 16 진수 이전의 2 진수 속기로 사용되었습니다.
ocodo

Slomojo는 오른쪽, 8 진수, 8 진수는 3 비트를 사용했으며 16 진수, 16 진수는 4 비트를 사용했습니다. Octal은 모든 사람들이 0에서 7까지의 숫자를 나타내는 것을 알고 있다는 이점이있었습니다. 16 진수를 사용하지 않은 사람들은 종종 "숫자"A에서 F로 신비화되었습니다.
Jim C

0

나는 최근에이 Q / A와 약 1 년 전에이 길을 여행하기 시작했습니다. 나는 이것이 내 자신의 관련 질문과 관련하여 매우 좋은 자료와 참조 페이지임을 알게 될 것입니다.


1 부 :- 서문-

나 자신에 대해 조금 :

내가 아직도 초등학교에있을 때 80 년대 중반에서 후반에, 나는 50 년대부터 80 년대까지의 정크 스테레오, VCR 및 기타 전자 장치를 분리하고 회로 보드를보고 항상 어떻게 알고 싶었는지 알고 싶었습니다. 작동 ... 실제로 방송 신호를 수집하고, 오디오, 비디오를 생성하고,이 작업을 수행하는 등의 작업을 수행했습니다. 여기에서 저항, 커패시터, 다이오드 및 트랜지스터와 같은 개별 부품을 인식 할 수 있었지만 그렇지 않았습니다. 그들이 어렸을 때 그들이 무엇을했는지, 어떻게 기능했는지 아십시오.

수년 동안 저는 항상 수학, 물리 및 화학 분야에서 탁월했습니다. 나는 수학을 고도로 이해했으며 나중에 온 중학교와 고등학교 시절의 간단한 또는 기본 회로를 읽을 수도 있었지만 논리 게이트와 그 구성 방법에 대해 배우지 못했습니다 ... Logic, Probability and Statistics Honors 클래스에서 고등학교의 부울 대수를 배우십시오. 모든 수학 및 과학 수업은 명예 수업이었습니다. 저는 커뮤니티 칼리지에서 2 학기까지 미적분학을 듣지 않았습니다. 나는 College Algebra에서 시험을 마치고 Trigonometry를 재교육 과정으로 이수했습니다. 교실에서 내 최고 수준의 수학은 단일 변수의 미적분학 II입니다.

3-4 살 정도되었을 때부터 비디오 게임을 해왔습니다. 어린 시절 저는 아타리, NES, 세가 제네시스, PS1을 가졌습니다. 나이가 들었고 10 대 후반과 20 대 초반에 저는 PS2와 SNES를 선호하는 선정 타이틀로 획득했습니다. 이것 또한 Doom!

나는 항상 열렬한 콘솔 및 PC 게이머였으며 여기에는 핀볼 및 아케이드 게임이 포함되지 않습니다.

90 년대 초 크리스마스 때 약 12 ​​세가되었을 때 첫 PC를 받았습니다. DOS 6.0과 Win 3.11 또는 OS / 2의 시대. 그 이후로 저는 항상 "Windows"운영 체제 제품군과 제가 가지고 있던 모든 시스템에 대해 잘 알고있었습니다. 학교 나 대학에서 Apple 또는 Mac에 대한 경험이 제한적이지만 Linux 시스템에서 작업 할 수있는 권한이 없었습니다. 나는 Cygwin을 가지고 있으며 bash를 배우는 데 손을 보았지만 Dos 또는 Command Prompt 구문에 익숙합니다.

90 년대 초반에 PC-World 사본을 두 개나 얻어서 코드 스 니펫을 QBasic에 입력하여 잘 모르고 해당 프로그램을 작동 시키려고했습니다. 성공한 유일한 것은 홈 키의 키 누름을 다른 벨소리로 바꾸는 프로그램이었습니다. 나는 휴대 전화의 벨소리를 의미하지 않는다 나는 당신이 키를 누르고있는 한 연속 주파수를 의미합니다.

전자 장치가 디지털 및 논리 수준의 회로 내에서 어떻게 작동하는지 알고 컴퓨터를 프로그래밍하는 방법을 배우고 싶었지만 항상 내 자신의 비디오를 만들고 싶어했습니다. 계략. 90 년대 초에도 Frogger와 Tetris 게임을 만들고 싶었습니다.


이것은 컴퓨터 과학 분야에서 가장 어려운 프로그래밍 또는 소프트웨어 개발 유형 중 하나 인 3D 게임 엔진 디자인을 해결하려는 저의 동기가되고 욕구가되었습니다. Computer Science에는 다른 어려운 분야도 있지만, 개별 구성 요소 또는 하위 엔진에 기술 및 속성이 필요하므로 복잡한 게임 엔진에는 일반적으로 거의 모든 것이 포함됩니다.

고등학교 시절부터 프로그래밍에 대한 배경 지식이 있었지만 이것은 끔찍한 Visual Basic으로 제한되었습니다. 1999 년 고등학교를 졸업 한 후 몇 년이 지나서야 2002-2003 년경에 C / C ++를 배우고 배우기 시작했습니다. 오늘날까지도 컴퓨터 공학이나 컴퓨터 공학에 대한 대학 수업 경험은 없지만 헌신과 결심, 나는 컴퓨터, 하드웨어, 프로그래밍, 알고리즘 등에 관한 모든 개념에 대해 배웠으며 여전히 가능한 한 많이 배우고 있습니다 ...

C / C ++을 배우는 초기에는 인터넷에 액세스했지만 인터넷은 초기 단계에 있었으며 Amazon, Youtube, Facebook 등의 웹 사이트는 아직 존재하지 않았지만 여전히 56k의 시대였습니다. 두 번째 전용 회선이없는 경우 전화선을 연결하는 모뎀을 다이얼하십시오. 이미지가 화면에 렌더링되는 데 몇 분이 걸리므로 지속적인 비디오 재생은 신경 쓰지 마십시오.

따라서 C ++로 프로그래밍하는 방법을 연구하고 배우는 데있어 리소스는 제한적이며 대부분 텍스트 형식이었습니다. 초창기 인터넷 튜토리얼 시절부터 프로젝트를 수행하려고 할 때, 그 프로젝트의 대부분은 완전하지 않았고, 작가는 전문가이거나 대학생이었으며 독자는 컴파일과 같은 필요한 많은 개념에 이미 익숙했다는 많은 가정을했습니다. , 링크 및 디버깅 및 라이브러리 통합.

이러한 주제에 대해 전혀 모르는 사람은 무엇이 잘못되었는지, 문제를 해결하는 방법 및 올바르게 작동하는 방법을 모르기 때문에 상실됩니다. 자원이 매우 제한적인 당시에는 시행 착오를받는 데 많은 시간이 걸렸습니다. 이 웹 사이트에서 지금 할 수있는 것과 같은 도움을 요청하거나 cppreference 에서 찾을 수있는 자세한 설명을 찾을 수 없었습니다! 당신이 개인적으로 누군가를 모른다면 도움을 청할 사람이 많지 않았습니다!

시간이 지남에 따라 나는 여기저기서 내 지식의 일부를 향상 시켰고 결국 인터넷은 DSL로 향상되었으며 이제는 초고속 인터넷, 웹 사이트가 더 상호 작용하고 비디오가 나타나기 시작했으며 시간이 지남에 따라 비디오 품질이 좋아졌습니다. 유튜브가 나타나기 시작하고 연구 측면에서 일이 조금 쉬워졌습니다. 점점 더 많은 튜토리얼을 쉽게 이용할 수있게되었으며 일부는 다른 사람들이 나쁜 관행을 가르쳤을 때 유용하고 유용했습니다 ...

또한 개발에 필요한 도구를 찾고 획득하는 데 많은 시간을 보냈습니다. 언어 구문, 컴파일러 및 컴파일 프로세스, 링크, 빌드 및 디버깅을 배워야했습니다. 그런 다음 사용 가능한 다양한 라이브러리 및 API와 이러한 종속성을 모두 연결하도록 프로젝트 또는 솔루션을 구성하는 방법에 대해 배워야했습니다.

수년 동안 저는 C ++ 언어가 시간이 지남에 따라 성장하고 발전하며 적응하는 것을 보았습니다. 처음에는 수년 동안 거의 동일하게 유지되었지만, 지난 10 년 동안 처음부터이 짧은 범위 내에서 크게 바뀌 었습니다.

C ++은 다재다능 함, 강력 함, 풍부한 기능 세트 및 발로 자신을 쏠 수있는 능력으로 인해 완전히 마스터하기 가장 어려운 언어 중 하나이기 때문에이 모든 것을 언급합니다! 그리고 모든 경고에도 불구하고,이 유형의 개발에 대한 표준으로 최고의 업계에서 사용되는 가장 강력하고 선호되는 언어 중 하나입니다. 올바르게 수행되면 빠르고 간결하고 신뢰할 수 있으며 가장 작은 발자국.

그 이후로 3D 그래픽 프로그래밍 및 게임 엔진 디자인을 배우려는 의도와 집중으로 수년 동안 C / C ++에서 자체 교육을 받았습니다. 나는 100 ~ 1,000 시간의 검색, 연구 및 그 밖의 지식을 읽고, 배우고, 유용한 작업 제품 및 응용 프로그램의 설계에 적용하는 것에 더 많은 시간을 투자했습니다. 나는 항상 기술과 기술을 향상시키기 위해 더 많은 것을 배우고 싶어하는 의지와 열망을 가지고있었습니다.


이것은 첫 번째 단계였으며 C / C ++ 및 C #에서 수행 한 DirectX 9.c를 처음부터 읽고 작업하기 시작했습니다. 그런 다음 DirectX 10 및 레거시 OpenGL 1.0으로 옮겼습니다. DirectX 11과 OpenGL 3.x-4.x에서 왔으며 이제는 Vulkan에서 손을 even습니다.

텍스트와 비디오 형식의 다양한 온라인 자습서를 통해 성공적인 게임 엔진을 구축했습니다. 나는 이미 수학에 대해 강한 배경을 가지고 있다고 말했지만 그것은 미적분학 I & II로 제한되었습니다. 나는 대학에서 내 Calculus 기반 물리학 수업에 대해 약간의 지식을 가지고있는 Vector Calculus를 가르쳐야했지만 Affine Transformations and Analytical Geometry가있는 Linear Algebra에 관해서는 특정 방정식, 함수, 방법, 알고리즘 및 개념이 필요했습니다. 그런 다음 그것들을 효율적이고 읽기 쉽고 신뢰할 수 있고 재사용 가능한 코드로 변환하여 수백에서 수천 시간의 디버깅을 가능하게하는 일반적이고 버그가없는 코드로 변환하는 방법을 배워야했습니다.

메모리 관리, 레퍼런스 카운팅, 인스 턴싱, 재귀 등을 포함하는 주제와 알고리즘을 배우는 것은 놀라운 여정이었습니다. 방대한 게임 엔진의 모든 구성 요소는 아니지만 많은 부분에서 사용됩니다. 여기에 그것들을 모두 나열 할 수는 있지만 3 또는 4 개의 답변 공간을 채울 수있는 충분한 정보입니다. 그러나 하위 주제가 아닌 일반 주제 목록을 포함시킬 것입니다.

다음은 모든 다양한 렌더링 기술, 렌더링 및 쉐이더 파이프 라인 설정, 쉐이더를 통한 음영 및 조명 기술, 사전 및 사후 처리, 프레임 버퍼, 백 버퍼를 포함하는 모든 기능을 갖춘 게임 엔진으로 구성된 주제 또는 주제 목록입니다. , 이미지 로딩, 오디오 및 모델 로딩 및 구문 분석, 수동 재질 매핑, 객체 변환, 카메라 유형, 장면 그래프 계층 구조, 텍스처, 오디오, 글꼴 및 셰이더 및 메모리 관리, 예외 처리 기능이있는 로깅 시스템, 멀티 스레드 및 병렬 프로그래밍 기술, 네트워킹, 물리 엔진, 충돌 감지, 입자 생성기, 애니메이션, 게임 AI, 지형 생성, 스카이 박스 및 스카이 돔, 워터 렌더링,폴리 지 및 기타 ..., 텍스트 렌더링, HUD 오버레이, 인벤토리, 맵 및 매크로 생성, 상태 시스템 및 상태 시스템을위한 텍스처 글꼴이있는 GUI, 마지막으로 파서를 작성하여 자체 스크립트 언어를 작성하여 이러한 오브젝트를 자동화 응용 프로그램 시작시 데이터 컨테이너에 데이터 개체와 구조를 채우도록 데이터 파일을로드하기 만하면 다시 컴파일하지 않고도 엔진 내에서 데이터 값을 변경할 수 있습니다.마지막으로 구문 분석기를 작성하여 자체 스크립트 언어를 작성하여 이러한 오브젝트의 많은 부분을 자동화하여 데이터 파일에로드하여 데이터 오브젝트 및 구조를 해당 컨테이너에 채우는 것만으로 다시 컴파일하지 않고도 엔진 내에서 데이터 값을 변경할 수 있습니다. 응용 프로그램 시작시.마지막으로 구문 분석기를 작성하여 자체 스크립트 언어를 작성하여 이러한 오브젝트의 많은 부분을 자동화하여 데이터 파일에로드하여 데이터 오브젝트 및 구조를 해당 컨테이너에 채우는 것만으로 다시 컴파일하지 않고도 엔진 내에서 데이터 값을 변경할 수 있습니다. 응용 프로그램 시작시.


몇 년 동안 나는 컴파일러, 어셈블러 및 간단한 운영 체제에 대해 배우고 싶었던 어셈블리 언어를 배우고 싶어했습니다. 내부 작업, 빌드 및 설계 방법을 의미합니다.

시간이 흐른 다음 나는 조금씩 물러서서 하드웨어 에뮬레이션을 배우기 시작했습니다. 나는 특히 NES에 초점을 맞추었지만 일반적으로 CPU의 하드웨어 에뮬레이션을 배우고 싶었습니다. 이를 통해 이미 개념을 알고있는 명령어 세트와 인텔 x86 제품군에 어느 정도 익숙해졌지만 6502 명령어 세트를 배워야했습니다.

그러나 이것으로 뛰어 들면서 더 많은 연구를했고 엔지니어링 관점에서 Instruction Set Architecture에 대해 배우기 시작했습니다. 이를 통해 로직 게이트에서 CPU를 구축하는 방법과 다른 다양한 전기 부품과 함께 트랜지스터로 로직 게이트를 구축하는 방법을 배울 수있었습니다. 그래서 나는 위에서 아래로 두 가지 관점에서 이것에 대해 배우게되었습니다. 두 방법 모두 매우 효과적이었으며 두 가지 방법 모두 소프트웨어를 통해 하드웨어를 강화하는 다리나 틈새를 만드는 데 도움이된다고 생각합니다.

이것으로부터 나는 불리언 대수를 새로 고쳐야했고, K-Maps, Implication Tables, State Machines Mealy와 Moore 그리고 이진 논리와 산술과 물리 논리 게이트와 집적 회로와 관련된 다양한 것들에 대해 배우게되었습니다. 그리고 이것은 내가 Logisim과 함께 일하기 시작했고 HDL, VHDL, Verilog 등을 배우기 시작한 최근의 저에게로 돌아갑니다.

나는 지난 15-18 년 동안 여가 시간에이 모든 것을 배우고 있습니다.


몇 년 동안 나를 안내해 준 사이트와 링크는 다음과 같습니다. 내가 처음부터 배운 많은 사이트가 더 이상 존재하지 않거나 링크를 잃어 버렸거나 기억하지 못하거나 검색 엔진이 검색 목록의 맨 뒤로 검색을 밀어 넣었을 때 이러한 사이트 중 대부분은 최근에 ...

  • 언어-C ++

  • 3D 그래픽 자습서 및 리소스 웹 사이트

  • 유튜브 시리즈와 채널 은 하드웨어, 컴퓨터 및 전기 공학뿐만 ​​아니라 위의 주제를 다룹니다. 나열 할 항목이 너무 많으므로 여기에 가장 유용하고 유용한 항목을 몇 개 나열하겠습니다. 링크를 제공하지는 않지만이 채널에서 YouTube를 검색 할 수 있습니다.

    • 3Blue1Brown- 고급 수학
    • Bisqwit- 고급 C / C ++ 프로그래밍 (응용 프로그램 프로젝트) -NES 하드웨어 에뮬레이터
    • Jason Turner- 고급 현대 C ++ 프로그래밍 기술
    • javidx9- 고급 C / C ++ 프로그래밍 (애플리케이션 프로젝트) -NES 하드웨어 에뮬레이터 / 일부 어셈블리
    • MIT OpenCourse- 수학 및 컴퓨터 과학의 대학 과정
    • Bilkent 온라인 코스 -컴퓨터 과학 및 컴퓨터 공학 (CPU Design MIPS) 대학 과정
    • Cherno- 고급 C / C ++ 프로그래밍 주제 및 응용 프로그램-게임 엔진 개발
    • Ben Eater- 하드웨어 엔지니어링-브레드 보드를 통한 실용적 응용
    • Neso Academy- 하드웨어 공학-이론 및 개념
    • Socratica- 파이썬 프로그래밍
    • 간단히 말해서 -하드웨어 공학-이론과 개념
    • 비트 단위 -고급 C / C ++ 하드웨어 에뮬레이션을 통한 어셈블러 설계
    • Bo Qian- 데이터 구조 및 알고리즘에 관한 C ++ 주제.
    • LineByLine- 불칸 프로그래밍
    • 조슈아 쉬커 -불칸 프로그래밍
    • www.MarekKnows.com -C ++, 3D 수학 및 게임 엔진 개발

그리고 이것들은 내가이 주제에 대해 가지고있는 다양한 책들 중 일부를 고려하지 않습니다.

-참고-이 내용은 본인의 개인적인 경험을 읽은 독자에게만 전달되는 메시지이므로 원래 질문에 답변하거나 언급하려는 시도는 없습니다. 내가 시간이있는 다음 며칠 동안; 유용한 링크를 참조 및 리소스 집합으로 제공하면서 OP의 질문에 대한 내 생각을 제공하기 위해 후속 답변을 추가하고 여기에 링크를 포함 하고이 메모를 수정하기 위해이 답변을 업데이트합니다. 늦었고 현재 이미 작성한 것을 교정하고 편집 할 시간이 없습니다. 할 수있을 때 할게요 "


이 답변이나 게시물을 방금 업데이트했습니다. 나는 실제로 질문에 대답 할 2 부를 추가하려고했지만 그렇게 할 평판이 충분하지 않습니다. 두 번째 답변을 추가하려면 필요한 평판 포인트를 구축하는 데 약간의 시간이 걸립니다. 이 게시물은 실제 답변이 아니지만 참조로 사용하고 내 진정한 답변의 추론에 대한 표를 찾습니다. 소프트웨어와 하드웨어 간의 격차를 해소하기 위해 위에 나열된 리소스 중 일부가 필요합니다.
Francis Cugler

-2

핵심은 CPU는 대개 상태 머신 일뿐입니다. 따라서 로직 게이트와 플립 플롭 또는 레지스터가 어떻게 상태 머신을 만드는지 이해해야합니다.

상태 머신은 입력과 현재 상태를 가져 와서 부울 (및 잠재적으로 산술) 논리를 통해 실행 한 다음 출력과 다음 상태를 제공합니다. 입력 중 하나가 명령어 레지스터 일 수 있습니다. 출력 중 하나는 소스가 명령 레지스터를 다시로드하기위한 활성화 및 선택 일 수 있으며, 프로그램 카운터로 작동하는 다른 레지스터를 증가 시키거나로드 할 수도 있습니다. 이를 통해 주소 지정 가능한 메모리와 함께 명령을 순서대로 지정할 수 있습니다.

명령을 시퀀싱하는 방법이 있으면 논리를 사용하여 이러한 명령 비트와 현재 상태를 다른 제어 비트로 디코딩 할 수 있습니다. 이러한 제어 비트 중 일부는 산술 및 워드 전체 논리를 수행 할 수있는 일련의 논리를 제어하는 ​​입력 역할을 할 수 있습니다.이를 ALU라고합니다. 다른 비트는 데이터를로드하거나 ALU에 대한 입력을 선택할 수 있습니다. 다른 비트는 ALU 결과를 저장할 위치를 말할 수 있습니다. 또는 주소 지정 레지스터를로드하십시오. 또는 메모리 나 다른 출력에 쓰십시오. 기타.

명령어 세트를 설계하는 과정은 디코딩 될 때 모든 레지스터와 상태 머신 시퀀싱을 제어하는 ​​비트 조합을 파악하는 것입니다. 이것은 수천 가지 다른 방법으로 이루어지고 (재) 최적화되었습니다.

이 사소한 주제에 대해 최소한 3 단계의 대학 교과서가 있습니다.


2
이것은 MOV 작업이 이진 값으로 포함되는 방법을 설명하지 않습니다. 이것은 명령 MOV 연산이 값, 우리가 사용하는 키워드라는 것을 언급하지 않으므로 16에서 32 비트 이진 값을 기억할 필요가 없습니다.
Ramhound
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.