인텔 코드를 디스 어셈블리 출력에 일치
나는 (SO에 대한 모든 것을 묻는 대신) 인텔 참조 페이지를 사용하여 op 코드를 찾고 배우기 시작했습니다. 내 이해가 정상인지 확인하고 기본 asm 프로그램과 인텔 명령어 코드 사이의 출력에 대해 몇 가지 질문을하고 싶습니다.
다음은 다양한 mov명령어를 rax-ish 레지스터 와 비교해야하는 프로그램입니다 ( "rax"와 32 비트 및 16 비트 구성 요소를 말하는 더 좋은 방법이 있습니까?).
.globl _start
_start:
movq $1, %rax # move immediate into 8-byte rax (rax) movl $1, %eax # move immediate into 4-byte rax (eax)
movw $1, %ax # move immediate into 2-byte rax (ax) movb $1, %al # move immediate into 1-byte rax (al)
mov $60, %eax
syscall
그리고 다음과 같이 분해됩니다.
$ objdump -D file
file: file format elf64-x86-64
Disassembly of section .text:
0000000000400078 <_start>:
400078: 48 c7 c0 01 00 00 00 mov $0x1,%rax 40007f: b8 01 00 00 00 mov $0x1,%eax
400084: 66 b8 01 00 mov $0x1,%ax 400088: b0 01 mov $0x1,%al
40008a: b8 3c 00 00 00 mov $0x3c,%eax
40008f: 0f 05 syscall
이제의 인텔 코드와 일치하며 MOV여기에 복사됩니다.
다음 네 가지 지침을 조정할 수 있습니다.
mov $0x1,%al->b0 01
YES , 인텔 상태 코드는b01 바이트 즉시 이동에 대해 [값에 대해 + 1 바이트]입니다.mov $0x1,%eax->b8 01 00 00 00
YES , 인텔 상태 코드는b81 바이트 즉시 이동에 대해 [값에 대해 + 4 바이트]입니다.mov $0x1,%ax->66 b8 01 00
아니요 , 인텔 상태 코드는b8그렇지 않습니다66 b8.mov $0x1,%rax48->c7 c0 01 00 00 00
N / A , 32 비트 명령어 전용. 나열되지 않았습니다.
이것과 관련된 내 질문은 다음과 같습니다.
- 왜
mov $0x1,%ax일치 하지 않습니까? 64-비트 코드에 대한 동일한 테이블이 있습니까? 아니면 그것을 찾는 방법이 무엇입니까?- 마지막으로 레지스터가 변경되면 코드가 어떻게 조정됩니까? 예를 들어 값을
%ebx또는%r11대신 이동하려는 경우 입니다. 이 룩업 테이블에서 보이는 것처럼 '코드 조정'을 어떻게 계산합니까?eax'예제 코드 등록'에 대한 레지스터 만 제공합니다 .
답변
다음 명령어의 의미를 변경하는 접두사 "opcodes"(개념)가 누락되었습니다. IA32 매뉴얼 의 볼륨 2, 섹션 2.1.1 및 2.2.1에서 이에 대해 설명합니다. 2.1.1에서 우리는 다음을 얻습니다.
피연산자 크기 재정의 접두사는 66H를 사용하여 인코딩됩니다 (66H는 일부 명령어의 필수 접두사로도 사용됨).
따라서 66 접두사는 피연산자 크기를 기본 32 비트에서 16 비트로 변경합니다. 따라서 mov $1,%ax(16 비트)는 mov $1,%eax66 접두사 만있는 (32 비트)와 동일 합니다.
마지막 경우 ( mov $1, %rax)는 실제로 다른 명령어를 사용하고 있습니다.
REX.W + C7 /0 io MOV r/m64, imm32 Move imm32 sign extended to 64-bits tor/m64.
여기서는 A 대신 레지스터로 상수를 이동합니다. 명령어는 1 바이트 더 크지 만 32 비트를 64 비트 레지스터로 이동할 수 있으므로 8 바이트 대신 4 바이트 상수 만 필요합니다. 1 (따라서 해당하는 48 b8 01 00 00 00 00 00 00 00보다 3 바이트 작음 )