2013-07-06 16 views
13

Come funziona la funzione C "memcpy" standard? Deve copiare un pezzo (grande) di RAM in un'altra area nella RAM. Dato che so che non puoi passare direttamente da RAM a RAM in assembly (con l'istruzione mov) quindi suppongo che utilizzi un registro CPU come memoria intermedia durante la copia?Come funziona l'implementazione interna di memcpy?

Ma come si copia? Da blocchi (come copierà da blocchi?), Da singoli byte (char) o dal tipo di dati più grande che hanno (copia in long long long - che è 12 byte sul mio sistema).

EDIT: Ok a quanto pare è possibile spostare i dati dalla RAM alla RAM direttamente, io non sono un esperto di montaggio e tutto quello che hanno imparato a conoscere il montaggio è da questo documento (X86 assembly guide), che menziona nella sezione riguardante l'istruzione MOV che non è possibile passare da RAM a RAM. Apparentemente questo non è vero.

+0

Questo è specifico della piattaforma. Si prega di specificare una piattaforma. –

+0

Io uso linux, mac e windows (32-bit, 64-bit e 32-bit rispettivamente) ma ho fatto questa domanda mentre usavo Linux. – hddh

risposta

14

Depends. In generale, non è possibile copiare fisicamente qualcosa di più grande del più grande registro utilizzabile in un singolo ciclo, ma non è proprio il modo in cui le macchine funzionano in questi giorni. In pratica, ti interessa molto meno di ciò che sta facendo la CPU e di più sulle caratteristiche della DRAM. La gerarchia di memoria della macchina giocherà un ruolo determinante cruciale nell'esecuzione di questa copia nel modo più rapido possibile (ad esempio, stai caricando intere linee di cache? Qual è la dimensione di una riga DRAM rispetto all'operazione di copia?). Un'implementazione potrebbe invece scegliere di utilizzare una sorta di istruzioni vettoriali per implementare memcpy. Senza fare riferimento a un'implementazione specifica, è effettivamente una copia byte per byte con un buffer a un posto.

Here's a fun article che descrive l'avventura di una persona nell'ottimizzazione memcpy. Il punto principale da portare a casa è che sarà sempre mirato a un'architettura e a un ambiente specifici in base alle istruzioni che è possibile eseguire in modo economico.

4

Un'implementazione banale di memcpy è:

while (n--) *s2++ = *s1++; 

Ma glibc usa di solito alcune implementazioni intelligenti in codice assembly. Le chiamate memcpy sono solitamente in linea.

In 86, il codice verifica se il parametro di dimensione è un multiplo letterale di 2 o un multiplo di 4 (usando gcc builtins funzioni) e utilizza un ciclo con movl istruzione (copia 4 bytes) altrimenti si chiama il caso generale.

Il caso generale utilizza l'assembly di copia blocco veloce utilizzando le istruzioni rep e movsl.

6

L'implementazione di memcpy è altamente specifica per il sistema in cui è implementata. Le implementazioni sono spesso assistite da hardware.

da memoria a memoria istruzioni mov non sono così rari - sono stati in giro almeno dal PDP-11 volte, quando si potrebbe scrivere qualcosa di simile:

MOV FROM, R2 
    MOV TO, R3 
    MOV R2, R4 
    ADD LEN, R4 
CP: MOV (R2+), (R3+) ; "(Rx+)" means "*Rx++" in C 
    CMP R2, R4 
    BNE CP 

La linea commentata è approssimativamente equivalente a C di

*to++ = *from++; 

CPU contemporanee hanno istruzioni che implementano memcpy direttamente: si carica registri speciali con gli indirizzi di origine e di destinazione, richiamare un comando copia della memoria, e lasciare CPU fare il resto.

+0

"sono in circolazione da almeno PDP-11 volte" - molto più a lungo. –

+0

@JimBalter Questo non mi sorprende affatto :) – dasblinkenlight