2017-09-14 2 views
0

저는 x86 디코더를 만들고 있습니다. 명령어의 니모닉을 계산하는 효율적인 방법을 이해하고 찾는데 어려움을 겪고 있습니다.x86 디코드 명령어 opcode 바이트

opcode 6 MSB가 opcode 비트라는 것을 알고 있지만 니모닉 테이블에서 6 비트를 사용하는 곳을 찾을 수 없습니다. 내가 찾은 유일한 니모닉 테이블은 6 비트 MSB가 아닌 전체 opcode 바이트 자체입니다.

opcode 바이트로 인코딩 된 니모닉을 디코드 할 수있는 효율적인 방법과 6 비트 MSB를 사용하는 테이블 참조가 있고 전체 opcode 바이트가 아닌 경우에 대해 묻고 싶습니다.

+0

하단 2 비트도 opcode의 일부입니다. 예를 들어, ['jcc'] (http://felixcloutier.com/x86/Jcc.html) 명령어는 0x70에서부터 모든 opcode 값에 대해 다른 니모닉을 가지고 있습니다 0x7F. 실제로 ModR/M 바이트의'/ r' 필드가 opcode의 일부이기도합니다. (예 :'shl'과'shr'). –

+0

최신 x86 기계어 코드의 문제점은 * 효율적/간단한 방법으로 디코딩 할 수 없다는 것입니다. 예를 들어'rep nop'은 실제로'pause'로 해독됩니다. 그렇지 않으면'rep bsf'가'tzcnt'로 해독됩니다 (BMI1이 지원되면 그렇지 않으면'bsf'로 해독됩니다). 따라서 다른 지침의 필수 접두어를 확인해야합니다. –

+0

@PeterCordes 내가 사용했던 리소스 중 하나는 http://www.c-jump.com/CIS77/CPU/x86/X77_0050_add_opcode.htm opcode의 유일한 6 개의 MSB가 아닌 예외가 있다는 것을 알고 있습니다. 바이트는 무릎 관절염을 나타냅니다. 그러나 일반 지시의 경우에는 그들이 말하는대로이 방법으로 보입니다. 저는이 정규 사례에 대해 어떻게 이들 6 가지 MSB를 사용하여 예에서했던 것처럼 니모닉을 결정할 수 있는지 묻고 있습니다. – Jorayen

답변

1

그러나 중복없는 니모닉에 대한 테이블을 저장하는 효율적인 방법은 없습니까?

이것은 알고리즘 및 데이터 구조 질문이되었습니다.

많은 opcode 테이블 항목 (최소한 0f 이스케이프 바이트가없는 테이블의 경우 : http://sparksandflames.com/files/x86InstructionChart.html)은 4 또는 2 그룹으로 반복됩니다. 즉, 동일한 6 또는 7 비트 접두어로 같은 연상 기호.

분명히 구조체의 256 개 항목 테이블은 간단하지만 중복됩니다. 매우 빠르며 사용하기 쉽습니다. 캐시 미스가 발생하지 않을 정도로 작기 때문입니다. (특히 공통 항목은 캐시에서 뜨거워 지므로 x86 코드는 동일한 연산 코드를 많이 사용합니다.)

공간에 단순 성과 성능을 교환 할 수 있습니다.

하나의 멤버가 낮은 2 비트으로 인덱싱 될 보조 테이블에 대한 포인터 인 구조의 64 개 항목 테이블을 가질 수 있습니다. 포인터가 NULL이면 명령어가 add/and/xor/등의 패턴을 따르고 낮은 2 비트는 피연산자 크기와 방향 (r/m, reg 또는 reg, r/m).

구조체에는 특정 접두사가있는 경우 다른 지침 (예 : rep noppause)으로 전환하기위한 항목이 필요합니다. 또한 AVX VEX 접두어는 다른 명령어의 잘못된 인코딩이었던 것을 사용합니다. x86은 현재의 모든 확장 기능에 대한 완전한 작업을 원한다면 디코딩하는 것이 아주 이상합니다.

실제로는 은 기능 포인터 테이블을 사용하는 것이 가장 간단하고 효율적일 수도 있습니다. 또는 const char* mnemonicint (*decode)(const char*mnemonic, const char *insn_bytes, unsigned prefix_bitmap) 기능을 가진 구조체, 많은 opcodes 같은 디코딩 기능을 가리킬 수 있지만 여전히 다른 니모닉을 얻을 수 있습니다. 때때로 함수는 전달 된 니모 닉을 무시할 것이지만 필요한 다른 시간은 무시합니다. 많은 디코드 함수가 호출하는 어드레싱 모드를 디코딩하는 공통 기능을 갖게됩니다.

동적 재 컴파일을하는 대신 해석하는 x86 에뮬레이터를 구현하는 방법과 매우 비슷합니다. 일반적인 디코드 루프와 함수 포인터를 통한 디스 패칭. 당신이 사용할 수


이보다 더 복잡한 데이터 구조는 접두사 나무 일명 radix trie이다. https://en.wikipedia.org/wiki/Trie#Bitwise_tries을 참조하십시오.

밀도가 너무 높아 조회 테이블이 훨씬 더 의미가 있기 때문에 바보 같은 시즌에 접어 들고 있습니다.(정의되지 않은 opcode는 거의 없습니다.)

+0

그렇다면 성능 (속도 현명)을 목표로하면 256 개의 엔트리 테이블을 저장하는 것이 최선의 선택일까요? 또한 구조체가 필요한 이유는 무엇입니까? 아마 모든 니모닉의 열거 형을 작성한 다음이 열거 형에 대한 색인 테이블로 256 항목 표를 작성한다고 생각합니다. 귀하의 생각은 무엇입니까? – Jorayen

+0

그래, 256 엔트리 테이블이 가장 잘 작동 할 것 같아. 여분의 디코드 단계를 선택하기위한 추가 분기가 그럴 가치가있을 것 같지 않습니다. –

+0

@ Jorayen : 다른 특수한 경우를 위해 별도의 테이블을 가지고 있지 않다면 구조체를 사용하여 니모닉을 보유하고 나머지 바이트를 피연산자로 디코딩하는 방법을 알려줄 것입니다. (예 :'jcc' /'call' 대'add''와'mul r/m32' 대'imul r, r/m32, imm32' 대 다른 특수한 경우). 그리고 특별한 경우를 위해 ModR/M의'/ r' 필드에서 3 개의 opcode 비트가 나오고이를 나타 내기 위해 (예 : 다른 테이블에 대한 포인터로). 모든 액세스에서 대부분의 구성원을 사용하는 하나의 구조체는 좋은 공간 위치를 제공하므로 캐시가 잘됩니다. –