2014-10-11 3 views
2
Dump of assembler code for function func4 
    <+0>: mov %rbx,-0x18(%rsp) 
    <+5>: mov %rbp, -0x10(%rsp) 
    <+10>: mov %r12,-0x8(%rsp) 
    <+15>: sub $0x18,%rsp 
    <+19>: mov %edi,%ebx 
    <+21>: mov %esi,%ebp 
    <+23>: test %edi, %edi 
    <+25>: jg 0x400fb2<func4+34> 
    <+27>: mov $0x0,%ebp 
    <+32>: jmp 0x400fd2<func4+66> 
    <+34> cmp $0x1, %edi 
    <+37>: je 0x400fd2<func4+66> 
    <+39>: lea -0x1(%rbx),%edi 
    <+42>: callq 0x400f90 <func4> 
    <+47>: mov %eax,%r12d 
    <+50>: lea -0x2(%rbx),%edi 
    <+53>: mov %ebp,%esi 
    <+55>: callq 0x400f90 <func4> 
    <+60>: lea (%r12,%rax,1),%eax 
    <+64>: add %eax,ebp 
    <+66>: mov %ebp, %eax 
    <+68>: mov (%rsp),%rbx 
    <+72>: mov 0x8(%rsp), %rbp 
    <+77>: mov 0x10(%rsp),%r12 
    <+82>: add $0x18,%rsp 
    <+86>: retq 

이것은 func4의 디스 어셈블 된 코드입니다. 그리고이 기능을 올바르게 이해했는지 아닌지 잘 모르겠습니다.폭탄 실험실 phase_4

I 여기 을 phase_4의 분해 코드를 작성하지 않은하지만 필요 "% D % D"를 입력하고, 최초의 정수 범위 내에 있어야 1 < = X < 4. 그래서되어야 1,2 또는 3입니다. % edi 레지스터의 값은 처음에는 7입니다. func4를 호출 한 후 0x10 (% rsp)과 % eax의 값을 비교 코드 그래서 func4를 호출 한 후 % eax 값을 알아야합니다.

나는 func4의 디스 어셈블 된 코드
put the stack 
ebx = edi 
ebp = esi 
if edi is not zero 
    if edi is one: then eax=ebp. 
        rearrange the stack 
        return. 
    else: edi = -0x1(rbx) 
      func4 
      r12d = eax 
      edi = -0x2(rbx) 
      esi = ebp 
      func4 
      eax = rax+r12+ebp 
      rearrange the stack and return. 
else 
    ebp=0 
    eax=ebp 
    return 

을 의미한다 생각하지만 내 이해, 나는 그것을 해결할 수 없습니다. 예를 들어 % rsp의 원래 주소가 0x7fffffffd5a8 인 경우 edi 값이 0이 될 때까지 주소가 더 작아집니다. 0x7fffffffd56f 값이 0이고 첫 번째 func4 호출의 끝이 이지만 그 이후 0x7fffffffd56e 값도 0이므로 두 번째 func4 호출이 끝나기 때문에 이고 모든 레지스터는 eax를 포함하여 0이됩니다.

두 번째 숫자의 대답이 0이라고 생각 했으므로 (1,0), (2,0), (3,0)은 항상 폭탄을 폭발시킵니다.

내가 틀렸어 도우니까?

+0

은, 일부 무의미한 부분을 다시 확인하여 분해를 가지고하시기 바랍니다) 디버거를 사용할 수있는 경우 물론

, 당신은 단지 코드 실행하자 eax의 값이 될 것입니다 무엇을 볼 수 있습니다 복사 - 붙여 넣기 오류를 나타냅니다. 'ebp'가'%'또는'$ 0x18' 대신에'$ px18'과 같이 누락되었습니다. 실제 코드를 올바르게 제공하지 않으면 알아 내기가 어렵습니다. – Jester

+0

@Jester 귀하의 의견을 보았습니다. 디스 어셈블 된 코드에는 몇 가지 실수가 있었으며 올바르게 수정했습니다. 이에 대해 알려 줘서 고마워. –

+0

자 이제 알맞은 의사 코드를 업데이트해야합니다.) – Jester

답변

1

ediesifunc4의 두 인수입니다. 이것은 표준 호출 규칙에 따르지만,이 레지스터는 초기화없이 사용되므로 그 값은 외부에서 가져와야한다는 사실에서 추론 할 수도 있습니다. 따라서 프로토 타입은 int func4(int a, int b)입니다.

라인 +23a > 0인지 확인하고 있으면 점프합니다. 그래서 조건이 거짓 인 경우 우리가 쉽게 발생하는 추적 할 수 있습니다 : +34a == 1 경우 확인하고 있습니다

if (a <= 0) return 0; 

라인, 두 번째 인 그렇다면, ebp의 현재 값이 반환됩니다,하지만이 esi에서 초기화 된 인수 b는 :

그렇지 않으면
if (a == 1) return b; 

, 선 +39 ... +55 재귀 func4를 호출합니다. 줄 +60 두 호출의 결과를 함께 추가하고 줄 +64b을 추가합니다. 그래서 우리는 :

return func4(a - 1, b) + func4(a - 2, b) + b; 

모든 입력에 대해 반환 값을 계산할 수 있습니다.

+0

phase_4의 분해 코드에서 esi는 phase_4의 두 번째 입력 인 0x14 (% rsp)로 설정되고 edi는 7로 설정됩니다. 설명, func4 (edi, esi)는 func4 (edi-1, esi) + func4 (edi-2, esi) + esi를 반환합니다. 따라서 func4 (7, esi)는 33 * esi를 반환합니다. 그리고 phase_4는 0x10 (% rsp)과 eax를 비교합니다. 따라서 phase_4의 첫 번째 입력은 33 * (phase_4의 두 번째 입력)이어야합니다. 나는 정확하게 이해 했는가? –

+0

오, 나는 phase_4를 해결했습니다! 답변 주셔서 감사합니다. 나에게 준 모든 도움에 정말 감사드립니다. :) –