2017-01-08 2 views
-1

Ich untersuche, wie Rep-String-Anweisungen arbeiten. Bezüglich der Beschreibung der Anweisungen hat die rep movsl zum Beispiel die folgende mnemonic.Wiederholungszeichenfolge verwendet zusätzliches Segment (ES) oder nicht?

Hierbei ist ES ein zusätzliches Segmentregister, das einen Versatz zum Anfang eines zusätzlichen Segments im Speicher enthalten sollte.

Der Pseudocode der Operation aussehen wie unten

while (CX != 0) { 
     *(ES*16 + DI) = *(DS*16 + SI); 
     SI++; 
     DI++; 
     CX--; 
} 

Aber es scheint, in Modell Flat-Speichers ist es nicht wahr, dass rep String mit zusätzlichem Segment tätig ist.

Zum Beispiel habe ich einen Test erstellt, der 2 Threads erstellt, die ein Array zu TLS (Thread lokalen Speicher) Array mit rep movs kopieren. Logischerweise sollte das nicht funktionieren, da TLS-Daten im GS-Segment und nicht in ES gespeichert werden. Aber funktioniert. Zumindest a sehen das korrekte Ergebnis beim Ausführen des Tests. Intel-Compiler erzeugt das folgende Stück Code für die Bewältigung.

movl  %gs:0, %eax         #27.18 
movl  $1028, %ecx         #27.18 
movl  32(%esp), %esi        #27.18 
lea  [email protected](%eax), %edi     #27.18 
movl  %ecx, %eax         #27.18 
shrl  $2, %ecx          #27.18 
rep              #27.18 
movsl             #27.18 
movl  %eax, %ecx         #27.18 
andl  $3, %ecx          #27.18 
rep              #27.18 
movsb             #27.18 

Hier verweist% Edi auf TLS-Array und rep movs Speicher dort. Falls rep mov implizit ES-Offset verwendet (was ich bezweifle), sollte dieser Code nicht das korrekte Ergebnis liefern.

Vermisse ich etwas hier?

Es ist der Test, den ich erstellt:

#define _MULTI_THREADED 
#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 

#define     NUMTHREADS 2 
#define     N 257 

typedef struct { 
    int data1[N]; 
} threadparm_t; 

__thread threadparm_t TLS_data1; 

void foo(); 

void *theThread(void *parm) 
{ 
    int    rc; 
    threadparm_t  *gData; 

    pthread_t self = pthread_self(); 
    printf("Thread %u: Entered\n", self); 

    gData = (threadparm_t *)parm; 

    TLS_data1 = *gData; 

    foo(); 
    return NULL; 
} 

void foo() { 
    int i; 
    pthread_t self = pthread_self(); 
    printf("\nThread %u: foo()\n", self/1000000); 
    for (i=0; i<N; i++) { 
     printf("%d ", TLS_data1.data1[i]); 
    } 
    printf("\n\n"); 
} 


int main(int argc, char **argv) 
{ 
    pthread_t    thread[NUMTHREADS]; 
    int     rc=0; 
    int     i,j; 
    threadparm_t   gData[NUMTHREADS]; 

    printf("Enter Testcase - %s\n", argv[0]); 

    printf("Create/start threads\n"); 
    for (i=0; i < NUMTHREADS; i++) { 
    /* Create per-thread TLS data and pass it to the thread */ 
     for (j=0; j < N; j++) { 
      gData[i].data1[j] = i+1; 
     } 
     rc = pthread_create(&thread[i], NULL, theThread, &gData[i]); 
    } 
    printf("Wait for the threads to complete, and release their resources\n"); 
    for (i=0; i < NUMTHREADS; i++) { 
     rc = pthread_join(thread[i], NULL); 
    } 

    printf("Main completed\n"); 
    return 0; 
} 

Antwort

0

Was Ihnen fehlt, ist, dass diese ops:

movl  %gs:0, %eax 
... 
lea  [email protected](%eax), %edi 

werden, um die Null-Basis-Adresse des lokalen Thread-TLS_data1 in %edi Laden, was mit dem Null-Basis-ES-Segment gut funktioniert.

+0

OK, Sie meinen, dass die Standardwerte der Segmentregister ES und GS gleich sind? In diesem Fall gibt es eine andere Frage, wie kann ich dieses Programm nicht funktionieren lassen? Was soll ich eigentlich tun, um den Wert von GS oder ES zu ändern, aber nicht die Montage? – Andrei

+0

Nein, sie sind fast sicher * nicht * gleich, aber das macht nichts. Der erste dieser beiden Befehle lädt einen Wert aus dem Block, auf den "% gs" zeigt, und dieser Wert ist ein (0-Basis-, dh '% ds' /'% cs'/'% es' -relativer) Zeiger auf der statische TLS-Block für den Thread. 'TLS_data1' wird dann als ein Offset zu diesem Zeiger gefunden, und wiederum ist diese Adresse nicht relativ zu% gs, sie ist relativ zu% ds oder% es (die gleich sind). – caf

+0

Danke für deine Antworten. Sie haben mich zum Nachdenken gebracht :) Auf IA32% gs: 0 Punkte auf den Thread Control Block. Aber dieser Zeiger ist eine virtuelle Adresse in DS, nicht GS. Das ist es. – Andrei

Verwandte Themen