2012-03-11 3 views
0

다음 예제를 제공하는 책을 읽었습니다 : 각 멤버는 다음 멤버의 주소가 네 번째 첫 번째 바이트 인 목록이 있습니다. 마지막 멤버 그것은 다음 구현이 잘못이라고 말할 0의 값을 가지고, 나는 이유를 이해하지 않습니다.어셈블리 - 무료 목록 구현이 잘못되었습니다.

freeList 
    mov eax, [ebp+8] 
    cmp eax, 0 
    jne cont 
    ret 
cont: 
    mov ebx, [eax] 
    mov [ebp+8], ebx 
    push eax 
    call free 
    pop eax 
    call freeList 

(I 올바른 구현을 필요로하지 않는, 내가 하나가 그냥 필요 이것으로 무엇이 잘못되었는지 이해하십시오)

고마워요.

+0

끝 부분의'call freeList'는 나에게 잘못되었습니다. 제 생각에 가장 좋은 추측은'jmp freeList'입니다. – Neil

+0

@Neil : 정답은 정말 jmp입니다. 전화가 뭐가 잘못 됐어? –

답변

2

잘못된 구현의 마지막 줄은 call freeList입니다. 그러나 (재귀 적) 호출이 완료되면, 그 라인 다음에 존재하지 않는 코드로 되돌아 가려고합니다. ret 명령어를 추가하면 코드가 작동하지만 일반적으로 코드를 디버깅 할 때를 제외하고는 모든 중간 호출을 볼 수있는 경우를 제외하고는이를 피하려고합니다. 대신 call freeList; ret을 간단하게 jmp freeList으로 단순화 할 수 있습니다. 디버깅 높은 수준의 코드

예 :

function freeList(list) { 
    if (list) { 
     var next = list->next; 
     free(list); 
     freeList(next); 
    } 
} 

당신은 최적화로 컴파일 할 경우, 컴파일러는 listnext 대처하고 jmp을 수행하여 freeList(next)에 재귀 호출을 기록 할 수 있지만이 파괴 것 list의 값 즉, 함수 디버깅을 시도 할 때 목록의 어떤 요소가 이미 해제되었는지 알 수 없습니다. 따라서 함수에서 문제를 디버그하려고 할 때이 최적화를 비활성화하고 싶을 것입니다.

+0

각'call X '이후에 항상'ret '라고 써야한다고 말하는 것이 맞습니까? –

+0

어떤 점에서 중단 (abort) 또는 종료 (exit) 또는 이와 유사한 치명적인 다른 것이 아니라면 호출이 다음 문장으로 돌아올 것이므로 어떤 것을 작성해야합니다. – Neil

0

스택 프레임을 호출하기 전에 설정해야하므로 함수를 호출한다고해서 직접 호출 할 수는 없습니다. 호출 한 후에 프레임을 풀면됩니다. 이것은 또한 대부분의 시스템 ABI (EAX, ECX 및 EDX 만 스크래치 레지스터 인)에 반대하는 EBX를 보존하지 않습니다.

인라인 코드 인 경우 현재 프레임을 풀어야합니다 아니).

관련 문제