개발관련/other

에뮬레이터의 작동 원리와 작성 방법

Rateye 2021. 11. 12. 11:34
728x90
반응형
질문 : 에뮬레이터는 어떻게 작동하며 어떻게 작성됩니까?

에뮬레이터는 어떻게 작동합니까? NES / SNES 또는 C64 에뮬레이터를 보면 놀랍습니다.

http://www.tommowalker.co.uk/snemzelda.png

특정 조립 지침을 해석하여 해당 기계의 프로세서를 에뮬레이션해야합니까? 그 밖에 무엇이 들어가나요? 일반적으로 어떻게 설계됩니까?

에뮬레이터 (특히 게임 시스템) 작성에 관심이있는 사람에게 조언을 해줄 수 있습니까?

답변

에뮬레이션은 다각적 인 영역입니다. 다음은 기본 아이디어와 기능적 구성 요소입니다. 나는 그것을 조각으로 나누고 편집을 통해 세부 사항을 채울 것입니다. 제가 설명 할 많은 것들은 프로세서의 내부 작동에 대한 지식을 필요로합니다. 어셈블리 지식이 필요합니다. 특정 사항에 대해 너무 모호한 경우이 답변을 계속 개선 할 수 있도록 질문 해주세요.

기본 아이디어:

에뮬레이션은 프로세서 및 개별 구성 요소의 동작을 처리하여 작동합니다. 시스템의 각 개별 부분을 만든 다음 하드웨어에서 와이어처럼 부분을 연결합니다.

프로세서 에뮬레이션:

프로세서 에뮬레이션을 처리하는 방법에는 세 가지가 있습니다.

  • 해석
  • 동적 재 컴파일
  • 정적 재 컴파일

이러한 모든 경로를 통해 전체적인 목표는 동일합니다. 코드를 실행하여 프로세서 상태를 수정하고 '하드웨어'와 상호 작용합니다. 프로세서 상태는 주어진 프로세서 타겟에 대한 프로세서 레지스터, 인터럽트 핸들러 등의 집합체입니다. 6502의 경우 레지스터를 나타내는 8 비트 정수 A , X , Y , P , S ; 16 비트 PC 레지스터도 있습니다.

해석을 통해 IP (명령 포인터 PC , 프로그램 카운터라고도 함)에서 시작하여 메모리에서 명령을 읽습니다. 코드는이 명령어를 구문 분석하고이 정보를 사용하여 프로세서에서 지정한대로 프로세서 상태를 변경합니다. 해석의 핵심 문제는 매우 느리다는 것입니다. 주어진 명령어를 처리 할 때마다이를 디코딩하고 필요한 작업을 수행해야합니다.

동적 재 컴파일을 사용하면 해석과 마찬가지로 코드를 반복하지만 단순히 opcode를 실행하는 대신 작업 목록을 작성합니다. 분기 명령어에 도달하면이 작업 목록을 호스트 플랫폼의 기계어 코드로 컴파일 한 다음이 컴파일 된 코드를 캐시하고 실행합니다. 그런 다음 주어진 명령 그룹에 다시 도달하면 캐시에서 코드를 실행하기 만하면됩니다. (BTW, 대부분의 사람들은 실제로 명령 목록을 작성하지 않고 즉시 기계 코드로 컴파일합니다. 이는 최적화하기가 더 어렵지만 충분한 사람들이 관심을 보이지 않는 한이 답변의 범위를 벗어납니다)

정적 재 컴파일을 사용하면 동적 재 컴파일과 동일하게 수행하지만 분기를 따릅니다. 프로그램의 모든 코드를 나타내는 코드 청크를 작성하면 더 이상 간섭없이 실행할 수 있습니다. 다음 문제가 아니라면 이것은 훌륭한 메커니즘이 될 것입니다.

이것들이 결합되어 99 %의 경우 정적 재 컴파일을 완전히 불가능하게 만듭니다. 자세한 정보를 위해 Michael Steil은 정적 재 컴파일에 대한 훌륭한 연구를 수행했습니다.

프로세서 에뮬레이션의 다른 측면은 하드웨어와 상호 작용하는 방식입니다. 여기에는 두 가지 측면이 있습니다.

  • 프로세서 타이밍
  • 인터럽트 처리

Processor timing:

특정 플랫폼, 특히 NES, SNES 등과 같은 오래된 콘솔에서는 에뮬레이터가 완전히 호환 되려면 엄격한 타이밍이 필요합니다. NES를 사용하면 CPU가 정확한 순간에 픽셀을 메모리에 넣어야하는 PPU (픽셀 처리 장치)가 있습니다. 통역을 사용하면 쉽게주기를 계산하고 적절한 타이밍을 에뮬레이션 할 수 있습니다. 동적 / 정적 재 컴파일을 사용하면 상황이 / lot / 더 복잡해집니다.

Interrupt handling:

인터럽트는 CPU가 하드웨어와 통신하는 기본 메커니즘입니다. 일반적으로 하드웨어 구성 요소는 CPU에 어떤 인터럽트를 처리하는지 알려줍니다. 이것은 매우 간단합니다. 코드가 주어진 인터럽트를 던지면 인터럽트 핸들러 테이블을보고 적절한 콜백을 호출합니다.

Hardware emulation:

주어진 하드웨어 장치를 에뮬레이션하는 데는 두 가지 측면이 있습니다.

  • 장치의 기능 모방
  • 실제 장치 인터페이스 에뮬레이션

하드 드라이브의 경우를 살펴보십시오. 이 기능은 백업 스토리지, 읽기 / 쓰기 / 포맷 루틴 등을 생성하여 에뮬레이션됩니다.이 부분은 일반적으로 매우 간단합니다.

장치의 실제 인터페이스는 조금 더 복잡합니다. 이것은 일반적으로 메모리 매핑 레지스터 (예 : 장치가 신호를 수행하기 위해 변경 사항을 감시하는 메모리 부분)와 인터럽트의 일부 조합입니다. 하드 드라이브의 경우 읽기 명령, 쓰기 등을 배치 한 다음이 데이터를 다시 읽는 메모리 매핑 영역이있을 수 있습니다.

더 자세히 설명하겠습니다.하지만이를 사용할 수있는 방법은 무수히 많습니다. 여기에 특정 질문이있는 경우 언제든지 문의하시면 정보를 추가하겠습니다.

Resources:

내가 소개 여기 꽤 좋은를 준 생각하지만, 추가적인 영역의 톤이있다. 질문이 있으면 기꺼이 도와 드리겠습니다. 나는 단지 엄청난 복잡성으로 인해 이것의 대부분에서 매우 모호했습니다.

위키피디아 필수 링크:

일반 에뮬레이션 리소스:

  • Zophar- 여기에서 에뮬레이션으로 시작하여 먼저 에뮬레이터를 다운로드하고 결국에는 방대한 문서 아카이브를 약탈했습니다. 이것은 당신이 가질 수있는 절대 최고의 자원입니다.
  • NGEmu- 직접적인 리소스는 많지 않지만 포럼은 타의 추종을 불허합니다.
  • RomHacking.net- 문서 섹션에는 인기있는 콘솔의 머신 아키텍처와 관련된 리소스가 포함되어 있습니다.

참조할 에뮬레이터 프로젝트:

  • IronBabel-Nemerle로 작성된 .NET 용 에뮬레이션 플랫폼이며 코드를 즉시 C #으로 재 컴파일합니다. 면책 조항 : 이것은 내 프로젝트이므로 뻔뻔한 플러그를 용서하십시오.
  • BSnes- 완벽한주기 정확도를 목표로하는 멋진 SNES 에뮬레이터.
  • MAME - 아케이드 에뮬레이터. 훌륭한 참조.
  • 6502asm.com- 이것은 멋진 작은 포럼이있는 JavaScript 6502 에뮬레이터입니다.
  • dynarec'd 6502asm- 이것은 내가 하루나 이틀 동안 한 작은 해킹입니다. 6502asm.com에서 기존 에뮬레이터를 가져 와서 엄청난 속도 향상을 위해 코드를 JavaScript로 동적으로 재 컴파일하도록 변경했습니다.

프로세서 다시 컴파일 참조:

부록

이 답변이 제출 된 지 1 년이 지났고 모든 관심을 기울여서 몇 가지 사항을 업데이트 할 때라고 생각했습니다.

아마도 지금 에뮬레이션에서 가장 흥미로운 것은 앞서 언급 한 Michael Steil에 의해 시작된 libcpu입니다. 재 컴파일 (정적 및 동적!)을 위해 LLVM을 사용하는 많은 수의 CPU 코어를 지원하기위한 라이브러리입니다. 그것은 엄청난 잠재력을 가지고 있으며 에뮬레이션을 위해 훌륭한 일을 할 것이라고 생각합니다.

emu-docs 는 또한 에뮬레이션 목적에 매우 유용한 시스템 문서의 훌륭한 저장소를 포함하는 내 관심을 끌었습니다. 나는 거기에서 많은 시간을 보내지 않았지만 훌륭한 자원이 많은 것 같습니다.

이 게시물이 도움이되어 기쁘고, 연말 / 내년 초까지이 주제에 대한 책을 끝낼 수 있기를 바랍니다.

출처 : https://stackoverflow.com/questions/448673/how-do-emulators-work-and-how-are-they-written
728x90
반응형