2016-11-21 6 views
0

기본적으로 C 함수를 호출하는 인라인 어셈블리를 사용하는이 함수는 반환 된 값을 가져 와서 해당 값을 문자를 반환하는 다른 함수에 매개 변수로 전달합니다. 유형 이미 성문화를 테스트 나는 C 코드를 사용하여 원하는 값을 반환 잘 작동했다인라인 어셈블리를 사용하여 C 함수에서 반환 된 문자 가져 오기

unsigned char codify(unsigned char parameter) { 
    unsigned char resp; 

    // Do something to the parameter 
    resp = 'b'; // asign value to resp 
    return resp; 
} 

의 기능과 성문화의

void convertText(FILE *arch, FILE *result) 
{ 
    int i = 0; 
    int n = arch->size; 

    _asm { 
    mov esi, 0 
whileS: 
    cmp esi, n 
    jge end 

    mov ebx, result 
    mov ebx, [ebx]result.information ; Pointer to an array of characters 

    push esi ; Push parameters to get5bitsFunc 
    push arch ; Push parameters to get5bitsFunc 

    call get5bitsFunc 
    pop arch ; Restore values 
    pop esi ; Restore values 

    push eax ; push get5bitsFunc returned value to codify as parameter 
    call codify 
    mov edi, eax ; <- HERE move returned value from codify to edi register 
    pop eax ; restore eax 

    inc esi 
    jmp whileS 
end: 

    } 
} 

생각합니다. 문제는 실행하고 내가 "-> 여기"로 eax에서 반환 된 값으로 표시된 줄에 인라인 어셈블리에서 convertText 코드를 디버깅 할 때 형식이 3424242이고 97가 아닌 ASCII 테이블에있는 것입니다. 나는 필요하다.

어떻게 char 값을 얻을 수 있습니까?

+0

'unsigned char'는 단지 1 바이트이고'eax'는 32 비트 (4 바이트) 레지스터입니다. 'codify()'가 단지 1 바이트를 반환한다면 반환 값은'al' ('eax'의 첫번째 바이트)에 저장되고'eax'의 나머지 부분은 그대로 유지됩니다 (이것은 쓰레기가 될 것입니다). 'codify()'를 호출하기 전에'xor eax, eax'를 권하고 있으므로 반환 값을 저장하기 전에 레지스터가 깨끗하다는 것을 알 수 있습니다. –

+0

@BrendonBoldt 네, 네가 옳았다. 네가 옳은지 확인할 수 있도록 대답으로 의견을 게시 할 수 있니? – ravelinx

+0

왜 당신은'pop eax; 복원 eax'? 확실히 다음 스택은'get5bitsFunc'를 호출하여 스택을 깨뜨리기 전에 스택을 재조정해야합니다. 따라서 지시 사항은 맞지만 의견은 완전히 잘못되었거나 오해의 소지가 있습니다. 비슷하게, 그 호출 이후의 POPs는 매우 이상합니다 (그리고 메모리로의 팝은 필요 이상으로 느립니다). 또한, EDI는 아무것도 읽을 수없는 것으로 보이므로 이상합니다. 나는 당신이 진짜 코드가 무엇이든간에 이것을 다듬 었다고 가정합니다. 성능 향상을 위해 인라인 asm에서 이것을 작성한다면 아마도 최적화 컴파일러보다 더 나빠질 것입니다. –

답변

3

Windows ABI는 char을 반환하는 함수가 없거나 EAX로 값을 부호 확장한다고 명시하지 않으므로 AL 이상의 바이트가 가비지라고 가정해야합니다. (이것은 the x86 and x86-64 System V ABI과 동일합니다 .ABI/calling convention docs에 대해서는 태그 위키를 참조하십시오).

codify()으로 전화하기 전에 EAX를 0으로 설정한다고 가정 할 수 없습니다. AL에서 char로 돌아 오기 전에 EAX를 스크래치 레지스터로 사용할 수 있지만 나머지 EAX에서는 쓰레기로 처리 할 수 ​​있습니다.

당신은 실제로 당신이 높은 바이트 쓰레기를 무시하고 싶은 어떤 다른 movzx esi, al (또는 MOVSX), 또는 mov [mem], al하거나 필요합니다.

1

부호없는 char은 1 바이트 뿐이며 eax은 32 비트 (4 바이트) 레지스터입니다. codify()이 1 바이트 만 반환하면 반환 값은 eax의 나머지 부분을 그대로두고 (eax의 첫 번째 바이트) al에 저장됩니다 (이로 인해 가비지가 발생 함). codify()을 호출하기 전에 xor eax, eax을 권하고 싶습니다. 반환 값을 저장하기 전에 레지스터가 깨끗한 것을 알 수 있습니다.

+0

올바른 아이디어, 잘못된 구현. codify는 리턴 값을 AL로두기 전에 전체 EAX를 임시로 사용할 수 있습니다. (질문에 대한 귀하의 의견에 회신하려고했는데 그때 내가 쓰고 있던 것은 독자적으로 답변으로 바뀌기 시작했습니다. 먼저 문제를 확인한 후에 답을 "훔쳐"죄송합니다. XOR에 대한 권장 사항을 수정했습니다.) –

+0

예; 나는 네가 옳다는 것을 알았다. 리턴하는 것 외에도'eax'를 만지지 않는 함수에서만 작동합니다. –