2016-08-08 5 views
3

매우 가끔 어셈블리를 사용합니다. 그래서 내가 다루어야하는 작은 코드 조각을 디코딩하기 위해 좀 더 전문가의 도움이 필요합니다.x64 JMP 명령어의 어셈블리 디코드

0000: 48 ff 25 61 57 07 00 rex.W jmp QWORD PTR [rip+0x75761]  # 0x75768 
0007: cc      int3 

rip+0x75761 유지 8 바이트/64 비트 어드레스로 메모리 간접 점프 절대 어드레스 있도록 점프 타겟 바로 0007 + 0x75761 = 0x75768이다로부터로드된다?

+2

예, REX.W는 중복됩니다. – harold

+0

감사합니다. 불행하게도이 코드는 user32.dll 함수 중 하나에 대한 고객의 x64 Windows 10 설치에 있습니다. 그 코드가 표준 MS 코드가 아니기 때문에 거기에 어떻게 도달했는지는 알 수 없습니다. 그래서 나는 그것을위한 편의를 마련해야한다. – user118708

+0

이것이 64 비트 머신 코드입니까? 32 비트 코드로 디스 어셈블 된 경우 '0x48'바이트는 'dec'또는 'inc'가됩니다. ('dec eax') 나는 생각한다. –

답변

2

이것은 Microsoft 컴파일러에서 생성되는 x86-64의 표준 테일 콜 시퀀스입니다.

예, 말한대로 64 비트 메모리 주소 인 0x75768으로 간접적으로 건너 뜁니다. 이 코드가 실행될 때 rip은 7과 같으므로 rip + 0x75761 == 0x7 + 0x75761 == 0x75768입니다. 이 코드는 무조건 제어를 주소 0x75768의 명령어로 전송합니다.

다음의 int 3은 단지 패딩이지만 벽돌 벽으로도 사용됩니다. 실행은 이전 명령의 무조건 분기 때문에이 시점에 도달해서는 안됩니다. 만약 그렇다면, CPU는 "break"인터럽트이기 때문에 트랩합니다.

REX.W 접두사의 경우 harold는 기술적으로 정확하지만 불필요하다고 생각할 수 있습니다. 다소 놀랍게도, 레지스터를 통한 간접적 인 점프가 x86-64에서 사용될 때 Windows는 스택 되감기가 성공적으로 이루어 지도록 REX.W 접두사를 요구합니다. 스택 되감기 코드는 이것을 내부적으로 신호로 사용합니다. Ross Ridge는 Windows x64에서 REX 접두사가 붙은 JMP 명령어의 목적에 대해 an excellent answer을 작성했습니다.

IP 상대 피연산자와의 간접 점프이기 때문에 엄격하게 필요하지는 않지만 컴파일러는 분명히 그것을 방출합니다. 이것을 다루는 논리는 아마도 그렇게 복잡하지는 않을 것이고 아마도 일관성을 위해 항상이 코드를 생성 할 것입니다. 또는 스택 언 와인딩 코드가 구현되는 방식에 대한 공식 문서가 포괄적이지 않을 수도 있습니다. 미안한 것보다 안전합니다. 추가 REX.W 접두어에는 실제적인 단점이 없기 때문입니다.

+0

REX.W는 Windows 10 주년 업데이트에 Microsoft에서 WIn32 API에 추가되었습니다. 선택적이라 할지라도 앞으로는 OS의 일부입니다. – user118708

+0

나는 당신이 말하는 것을 이해하지 못한다고 생각합니다. @user. API에 어셈블리 연산 코드를 어떻게 추가합니까? Windows 10과 함께 제공되는 코드가이 인코딩을 사용한다고 말하면 분명히 그렇습니다. 64 비트 Windows의 모든 버전에는 항상 있어야합니다. Windows 10 기념일 판의 32 비트 버전을 포함하여 32 비트 Windows의 버전은 없습니다. 그리고 이것이 "선택적"이유는 IP 관련 인코딩에 실제로 필요하지 않기 때문입니다. 간접 인코딩의 경우에만 필요합니다. 그것은 Windows 10에서 변경되지 않았습니다. 스택 unwinding 여전히 같은 방식으로 작동합니다. –

+0

잠깐만, 상대 점프가 아니에요. RIP 상대 주소 지정 모드를 사용하여 64 비트 절대 포인터를로드합니다. 이것은 간접 지정이없는 tailcall과'REX.W = 1 jmp rel32'와는 많이 다릅니다. –