문제

나는 일부 어셈블리를 이해하려고 노력하고 있습니다.

다음과 같은 어셈블리에 관심이 있습니다. testl 선:

000319df  8b4508        movl   0x08(%ebp), %eax  
000319e2  8b4004        movl   0x04(%eax), %eax  
000319e5  85c0          testl  %eax, %eax  
000319e7  7407          je     0x000319f0  

나는 그 점을 이해하려고 노력하고 있습니다. testl ~ 사이 %eax 그리고 %eax?이 코드의 구체적인 내용은 중요하지 않다고 생각합니다. 테스트 자체를 이해하려고 노력하는 것뿐입니다. 값이 항상 참이 아닐까요?

도움이 되었습니까?

해결책

그것은 여부를 테스트합니다 eax 0 또는 위 또는 아래입니다. 이 경우 점프는 다음과 같습니다 eax 0입니다.

다른 팁

그 의미 test 인수와 함께, 결과를 0을 확인하십시오. 따라서이 코드는 EAX가 0인지 아닌지 테스트합니다. je 0이면 점프합니다.

BTW, 이것은보다 작은 지시를 생성합니다 cmp eax, 0 이것이 컴파일러가 일반적으로 이런 식으로 수행하는 이유입니다.

테스트 명령은 피연산자간에 논리적 및 수술을 수행하지만 결과를 다시 레지스터에 기록하지는 않습니다. 플래그 만 업데이트됩니다.

예제에서 Test EAX, EAX가 0 인 경우 eAx가 0, 가장 높은 비트 세트와 다른 플래그 인 경우 부호 플래그를 설정합니다.

Zero 플래그가 설정되면 동일하면 점프가 동일합니다.

코드를 다음과 같은보다 읽기 쉬운 코드로 변환 할 수 있습니다.

cmp eax, 0
je  somewhere

기능이 동일하지만 일부 바이트가 더 많은 코드 공간이 필요합니다. 이것이 바로 컴파일러가 비교 대신 테스트를 방출 한 이유입니다.

test 처럼 and, 단, FLAGS만 작성하고 두 입력을 모두 수정하지 않은 채로 둡니다.2개로 다른 입력의 경우 일부 비트가 모두 0인지 또는 적어도 하나가 설정되어 있는지 테스트하는 데 유용합니다.(예: test al, 3 EAX가 4의 배수인 경우(따라서 하위 2비트가 모두 0인 경우) ZF를 설정합니다.


test eax,eax 모든 플래그를 정확히 같은 방식으로 설정합니다. cmp eax, 0 ~일 것이다:

  • CF 및 OF가 지워졌습니다. (AND/TEST는 항상 그렇게 합니다.0을 빼면 캐리가 발생하지 않습니다)
  • EAX의 값에 따른 ZF, SF 및 PF.(a = a&a = a-0)

(더 이상 사용되지 않는 AF(ASCII/BCD 명령어에서 사용되는 보조 캐리 플래그 제외). TEST에서는 정의되지 않은 상태로 둡니다., 하지만 CMP는 "결과에 따라" 설정합니다..0을 빼면 4번째 비트에서 5번째 비트로 캐리가 생성될 수 없으므로 CMP는 항상 AF를 지워야 합니다.


TEST는 더 작고(즉각적이지 않음) 때로는 더 빠릅니다(CMP보다 더 많은 경우에 더 많은 CPU에서 비교 및 ​​분기 작업으로 매크로 융합할 수 있음). 그게 test 레지스터가 0인지 아닌지 테스트하는 데 선호되는 관용구.

즉시값 0으로 CMP를 사용하는 유일한 일반적인 이유는 메모리 피연산자와 비교하려는 경우입니다(예: cmpb $0, (%esi) 암시적 길이의 C 스타일 문자열 끝에 종료 0바이트가 있는지 확인합니다.


AVX512F 추가 kortestw k1, k2 및 AVX512DQ/BW(KNL이 아닌 Skylake) 추가 ktestb/w/d/q k1, k2, AVX512 마스크 레지스터(k0..k7)에서 작동하지만 여전히 다음과 같은 일반 FLAGS를 설정합니다. test 정수와 같은 방식으로 OR 또는 AND 지시는 합니다.

kortestw k1,k1 SSE/AVX2를 대체하는 AVX512 비교 결과를 기반으로 분기/cmovcc/setcc를 수행하는 관용적 방법입니다. (v)pmovmskb/ps/pd + test 또는 cmp.


사용 jzje 혼란스러울 수 있습니다.

jz 그리고 je 문자 그대로 동일한 지시 사항입니다., 즉.기계 코드의 동일한 opcode. 그들은 동일한 일을 하지만 인간에게는 다른 의미를 갖습니다..디스어셈블러(및 일반적으로 컴파일러의 asm 출력)는 하나만 사용하므로 의미적 구별이 손실됩니다.

cmp 그리고 sub 두 입력이 같을 때 ZF를 설정합니다(예:빼기 결과는 0입니다). je (같으면 점프)는 의미상 관련된 동의어입니다.

test %eax,%eax / and %eax,%eax 결과가 0일 때 다시 ZF를 설정하지만 "동등성" 테스트는 없습니다.테스트 후 ZF는 두 피연산자가 같은지 여부를 알려주지 않습니다.그래서 jz (0이면 점프)는 의미상 관련된 동의어입니다.

이 코드 스 니펫은 일부 구조물이나 물체에 대한 포인터가 주어진 서브 루틴에서 나온 것입니다. 두 번째 라인은 포인터에서 해당 물건에서 값을 가져 오는 것입니다. 아마도 포인터 일 수도 있고 아마도 int 일 수 있습니다. 3 라인과 4 라인은이 값을 0에 대해 테스트하고 (포인터 인 경우 NULL) 0이면 다음 몇 가지 작업 (표시되지 않음)을 건너 뜁니다.

0에 대한 테스트는 때때로 즉각적인 리터럴 제로 값과 비교하여 코딩되지만 테스트 OP가 더 빨리 실행될 것이라고 생각했을 수도있는 컴파일러 (또는 인간?) 이름 변경. 그것은 명백한 Mov Eax, #0 (오래된 표기법을 사용하는 것이 아니라 콜로라도에서 누군가의 번호판에서 보았던 Xor Eax, eax)와의 레지스터를 지우는 아이디어를 보유한 것과 같은 트릭 가방에서 나온 것입니다. ).

ASM에서는 perl, tmtowtdi와 같이.

EAX가 0이면 조건부 점프를 수행합니다. 그렇지 않으면 319E9에서 계속 실행됩니다.

일부 프로그램에서는 버퍼 오버플로를 확인하는 데 사용할 수 있습니다. 할당 된 공간의 맨 위에는 0이 배치됩니다. 데이터를 스택에 입력 한 후 할당 된 공간의 시작 부분에서 0을 찾아 할당 된 공간이 오버플로되지 않도록합니다.

그것은 악용 운동의 STACK0 운동에 사용되어 오버플로되었는지 확인하고 거기에없고 0이 있는지 확인하면 "다시 시도해보기"가 표시됩니다.

0x080483f4 <main+0>:    push   ebp
0x080483f5 <main+1>:    mov    ebp,esp
0x080483f7 <main+3>:    and    esp,0xfffffff0
0x080483fa <main+6>:    sub    esp,0x60                     
0x080483fd <main+9>:    mov    DWORD PTR [esp+0x5c],0x0 ;puts a zero on stack
0x08048405 <main+17>:   lea    eax,[esp+0x1c]
0x08048409 <main+21>:   mov    DWORD PTR [esp],eax
0x0804840c <main+24>:   call   0x804830c <gets@plt>
0x08048411 <main+29>:   mov    eax,DWORD PTR [esp+0x5c] 
0x08048415 <main+33>:   test   eax,eax                  ; checks if its zero
0x08048417 <main+35>:   je     0x8048427 <main+51>
0x08048419 <main+37>:   mov    DWORD PTR [esp],0x8048500 
0x08048420 <main+44>:   call   0x804832c <puts@plt>
0x08048425 <main+49>:   jmp    0x8048433 <main+63>
0x08048427 <main+51>:   mov    DWORD PTR [esp],0x8048529
0x0804842e <main+58>:   call   0x804832c <puts@plt>
0x08048433 <main+63>:   leave
0x08048434 <main+64>:   ret

우리는 볼 수있었습니다 JGjle만약에 testl %edx,%edx. jle .L3우리는 쉽게 찾을 수 있습니다 jle정장입니다 (SF^OF)|ZF, %edx가 0, zf = 1이면 %edx가 0이 아니고 testl 이후 -1, of = 0, sf = 1이면 jump .sorry, gramp .sorry, gramp. 내 영어는 가난합니다

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top