2016-11-21 1 views
0

Ich habe diese Funktion, die Inline-Assembly, die im Grunde eine C-Funktion ruft, ruft den zurückgegebenen Wert und übergibt diesen Wert als Parameter an eine andere Funktion, die ein Zeichen zurückgibt.Get char von einer C-Funktion mit Inline-Assembly

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: 

    } 
} 

Denken Sie an kodifizieren als Funktion des Typs

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

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

ich bereits kodifizieren getestet und funktioniert gut, um den Wert der Rückkehr I C-Code wollen verwenden. Das Problem ist, dass, wenn ich den ConvertText-Code in Inline-Assembly in der Zeile ausführen und debuggen, die ich als "-> Here" markiert habe, ist der in eax zurückgegebene Wert etwas vom Typ 3424242 und nicht 97 oder höher in der ascii-Tabelle Ich brauche.

Wie kann ich den char Wert erhalten?

+0

Ein 'unsigned char' ist nur 1 Byte, während' eax' ein 32-bit (4 Byte) Register ist. Wenn 'codify()' nur 1 Byte zurückgibt, dann wird der Rückgabewert in 'al' gespeichert (das erste Byte von' eax'), während der Rest von 'eax' unberührt bleibt (was zu Müll führen würde). Ich würde 'xor eax, eax' vor dem Aufruf von' codify() 'empfehlen, damit Sie wissen, dass das Register sauber ist, bevor Sie den Rückgabewert darin speichern. –

+0

@BrendonBoldt Yeah Mann, danke, dass du Recht hattest, kannst du deinen Kommentar als Antwort posten, damit ich deinen überprüfen kann? – ravelinx

+0

Warum hast du 'pop eax; Wiederherstellung eax'? Sicherlich ist es nur, um den Stack neu zu balancieren, da die nächste Iteration es nicht liest, bevor es durch den Aufruf von "get5bitsFunc" verfälscht wird. Also ist die Anweisung richtig, aber der Kommentar ist total falsch/irreführend. In ähnlicher Weise sind die POPs nach diesem Aufruf super-komisch (und Pop in den Speicher ist langsamer als benötigt). Außerdem scheint EDI von nichts gelesen zu werden, das ist seltsam. Ich nehme an, Sie haben das von dem, was Ihr echter Code ist, abgeschnitten. Wenn Sie dies in Inline-Asm für Leistung schreiben, tun Sie wahrscheinlich schlechter als ein optimierender Compiler ... –

Antwort

3

Der Windows-ABI benötigt anscheinend keine Funktionen, die char zurückgeben, um den Wert in EAX zu Null- oder Zeichenerweiterung zu erweitern, so dass Sie annehmen müssen, dass die Bytes über AL Müll enthalten. (Dies ist das gleiche wie in the x86 and x86-64 System V ABI. Siehe auch das Tag-Wiki für ABI/Aufruf Konvention Dokumente).

Sie können nicht davon ausgehen, dass das Aufrufen von EAX vor dem Aufruf von codify() ausreichend ist. Es ist kostenlos, alle EAX als Scratch-Register zu verwenden, bevor Sie mit dem Zeichen in AL zurückkehren, aber im Rest von EAX Müll.

Sie müssen tatsächlich movzx esi, al (oder MOVSX) oder mov [mem], al oder was auch immer Sie tun möchten, um Müll in den hohen Bytes zu ignorieren.

1

Ein Zeichen ohne Vorzeichen ist nur 1 Byte, während eax ein 32-Bit- (4 Byte) -Register ist. Wenn codify() nur 1 Byte zurückgibt, wird der Rückgabewert in al (das erste Byte von eax) gespeichert, während der Rest von eax unberührt bleibt (was zu einem Müll führen würde). Ich würde empfehlen xor eax, eax vor dem Aufruf codify(), so dass Sie wissen, dass das Register sauber ist, bevor Sie den Rückgabewert darin speichern.

+0

Richtige Idee, falsche Implementierung. codify kann den gesamten EAX als temporär verwenden, bevor er seinen Rückgabewert in AL zurücklässt. (Ich wollte auf Ihren Kommentar zu der Frage antworten, aber das, was ich geschrieben habe, begann sich selbst zu einer Antwort zu verwandeln. Entschuldigen Sie, dass ich Ihre Antwort "gestohlen" habe, nachdem Sie das Problem zuerst identifiziert haben Du hast die Empfehlung an XOR angepasst.) –

+0

Ja; Ich sehe, dass Sie Recht haben. Es würde nur für Funktionen funktionieren, die 'eax' nicht berühren, außer zurückzukehren. –

Verwandte Themen