Così di recente stavo pensando di strcpy e di nuovo a K & R dove si mostra l'applicazione comePerché vs C++ 2010 compilatore produrre un codice assembly diverso per funzione simile
while (*dst++ = *src++) ;
Tuttavia ho erroneamente trascritto come:
while (*dst = *src)
{
src++; //technically could be ++src on these lines
dst++;
}
In ogni caso questo mi ha fatto pensare se il compilatore avrebbe effettivamente prodotto un codice diverso per questi due. Il mio pensiero iniziale è che dovrebbero essere quasi identici, dal momento che src e dst vengono incrementati ma mai usati. Ho pensato che il compilatore avrebbe saputo di non tentare di conservarli acutamente come "variabili" nel codice macchina prodotto.
Utilizzo di windows7 con VS 2010 C++ SP1 in modalità di rilascio a 32 bit (/ O2), ho ottenuto il codice di disassemblaggio per entrambe le incarnazioni precedenti. Per evitare che la funzione stessa faccia riferimento direttamente all'input e sia in linea, ho creato una dll con ognuna delle funzioni. Ho omesso il prologo e l'epilogo dell'ASM prodotto.
while (*dst++ = *src++)
6EBB1003 8B 55 08 mov edx,dword ptr [src]
6EBB1006 8B 45 0C mov eax,dword ptr [dst]
6EBB1009 2B D0 sub edx,eax //prepare edx so that edx + eax always points to src
6EBB100B EB 03 jmp docopy+10h (6EBB1010h)
6EBB100D 8D 49 00 lea ecx,[ecx] //looks like align padding, never hit this line
6EBB1010 8A 0C 02 mov cl,byte ptr [edx+eax] //ptr [edx+ eax] points to char in src :loop begin
6EBB1013 88 08 mov byte ptr [eax],cl //copy char to dst
6EBB1015 40 inc eax //inc src ptr
6EBB1016 84 C9 test cl,cl // check for 0 (null terminator)
6EBB1018 75 F6 jne docopy+10h (6EBB1010h) //if not goto :loop begin
;
Sopra ho annotato il codice, essenzialmente un singolo ciclo, solo 1 controllo per null e 1 copia di memoria.
Vediamo ora la mia versione errore:
while (*dst = *src)
6EBB1003 8B 55 08 mov edx,dword ptr [src]
6EBB1006 8A 0A mov cl,byte ptr [edx]
6EBB1008 8B 45 0C mov eax,dword ptr [dst]
6EBB100B 88 08 mov byte ptr [eax],cl //copy 0th char to dst
6EBB100D 84 C9 test cl,cl //check for 0
6EBB100F 74 0D je docopy+1Eh (6EBB101Eh) // return if we encounter null terminator
6EBB1011 2B D0 sub edx,eax
6EBB1013 8A 4C 02 01 mov cl,byte ptr [edx+eax+1] //get +1th char :loop begin
{
src++;
dst++;
6EBB1017 40 inc eax
6EBB1018 88 08 mov byte ptr [eax],cl //copy above char to dst
6EBB101A 84 C9 test cl,cl //check for 0
6EBB101C 75 F5 jne docopy+13h (6EBB1013h) // if not goto :loop begin
}
Nella mia versione, vedo che le prime copie del char 0a alla destinazione, poi i controlli per nulla, e poi finalmente entra nel ciclo in cui esso controlla per null di nuovo. Quindi il ciclo rimane in gran parte lo stesso, ma ora gestisce lo 0 ° carattere prima del ciclo. Questo ovviamente sarà subottimale rispetto al primo caso.
Mi chiedo se qualcuno sa perché al compilatore viene impedito di creare lo stesso codice (o quasi uguale) del primo esempio. Si tratta di un problema specifico del compilatore di ms o forse delle impostazioni del mio compilatore/linker?
qui è il codice completo, 2 file (1 funzione sostituisce l'altro).
// in first dll project
__declspec(dllexport) void docopy(const char* src, char* dst)
{
while (*dst++ = *src++);
}
__declspec(dllexport) void docopy(const char* src, char* dst)
{
while (*dst = *src)
{
++src;
++dst;
}
}
//seprate main.cpp file calls docopy
void docopy(const char* src, char* dst);
char* source ="source";
char destination[100];
int main()
{
docopy(source, destination);
}
Potresti pubblicare per favore gli interi pezzi di codice C con cui hai iniziato? Potrebbe essere diverso a causa delle dichiarazioni di src & dst, ma non sarei in grado di saperlo. I preamboli degli assemblatori che hai rimosso sono identici? Non è necessario incollarli se lo sono. – gbulmer
In entrambi i casi questo è l'intero codice, tranne che per l'epilogo e il prologo. La dichiarazione di entrambe le funzioni è __declspec (dllexport) void docopy (char * src, char * dst) – skimon
Questo è uno stile di codifica errato, perché molti lettori vedranno il segno "=" nell'espressione come errore di battitura per "==". –