mikrocontroller.net

Forum: Compiler & IDEs Woran macht Compiler Entscheidung fest TEXT_ | DATA_?


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: fixStackPointer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich schreibe gerade einen Compiler für eine selbst entwickelte Sprache - 
(sehr C nah). Als Referenz nutz ich den Microsoft-Compiler+Assembler, 
ich weiß es gibt auch andere. Bei folgendem Code
int main(int argc, char *argv[])
{
UINT64_T bbbb;
bbbb = 10;
intpr einPointer;
einPointer = &bbbb;
einPointer = 11;
}

erzeugt folgenes assembly:
  ;UINT64_T bbbb;
  ;bbbb = 10;
 mov         qword ptr [bbbb],0Ah  

  ;intpr einPointer;
  ;einPointer = &bbbb;
 lea         rax,[bbbb]  
 mov         qword ptr [einPointer],rax  

  ;einPointer = 11;
 mov         qword ptr [einPointer],0Bh


Der Pointer landet also der _TEXT Section. Woran macht das der Compiler 
in dem Falle aus? Mein Hobel legt die (lokale?) Variable auf dem Stack 
an...wie die Windows Calling Convention auch "empfiehlt".
Welche Bedingungen muss ich prüfen?

VG Jonas

Autor: Rufus Τ. F. (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
fixStackPointer schrieb:
> Der Pointer landet also der _TEXT Section.

Klär' mich auf: Woran erkennt man das an Deinem Assemblerschnipsel?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
fixStackPointer schrieb:
> Der Pointer landet also der _TEXT Section.

Das steht in Widerspruch zu:

> Mein Hobel legt die (lokale?) Variable auf dem Stack

Ansonsten könnte es helfen, die Frage so zu formulieren, dass 
Normalsterbliche ohne Kristallkugel sie verstehen.

Autor: Le X. (lex_91)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> fixStackPointer schrieb:
> Der Pointer landet also der _TEXT Section.
>
> Das steht in Widerspruch zu:
>
> Mein Hobel legt die (lokale?) Variable auf dem Stack
>
> Ansonsten könnte es helfen, die Frage so zu formulieren, dass
> Normalsterbliche ohne Kristallkugel sie verstehen.

"Mein Hobel" ist wohl der Eigenbau-Compiler des TE, der so die Aussage, 
den Pointer auf den Stack legt.
Der gezeigte Assemblercode stammt wohl vom nicht näher spezifizierten 
Microsoft-Compiler, der als Referenzimplementierung gilt.
Der TE möchte nun herausfinden welcher Compiler sich "richtig" verhält.
Kein Widerspruch.

Allerdings gibt der Assemblercode zu wenig Infos her.
Ich kann da nicht erkennen wo der Pointer liegt.

Autor: fixStackPointer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja es war schon spät...

Sorry, die Architekture ist x86_x64 im "echten" 64 bit Modus. Ich hab 
das Verhalten jetzt so implementiert das alle nicht initalisierten 
Variablen in DATA_ landen, alles was initialisiert werden muss in TEXT_ 
mit entsprechendem Initialiserungscode... sieht ganz gut aus. Vielen 
Dank für eure Beiträge :)

Autor: Markus F. (mfro)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
fixStackPointer schrieb:
> alles was initialisiert werden muss in TEXT_
> mit entsprechendem Initialiserungscode..

Vielleicht nicht unbedingt empfehlenswert, falls der Code auf einem OS 
laufen soll, das (per MMU) TEXT_ in ein read-only Segment steckt?

Autor: fixStackPointer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Vielleicht nicht unbedingt empfehlenswert, falls der Code auf einem OS
>laufen soll, das (per MMU) TEXT_ in ein read-only Segment steckt?

Stimmt, allerdings hab ich da auch ein andere Calling Convention. Ist 
aber soweit abstrahiert, also leicht leicht erweiterbar..

Erstmal Windows CV, dann kommt System-V...

Autor: fixStackPointer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Vielleicht nicht unbedingt empfehlenswert, falls der Code auf einem OS
>laufen soll, das (per MMU) TEXT_ in ein read-only Segment steckt?
Ich versuche das Gerade nochmal genau nachzuvollziehen, ist ein bisschen 
schwierig wenn man so tief im Detail steckt. Aber ich glaube ich 
verstehe jetzt was du meinst, das Binary wird ja schlussendlich mal von 
der Platte in den Ram geladen... allerdings muss das ja trotzdem 
irgendwie deterministisch laufen...irgendeine Idee?

Er wächst und gedeiht...
Aber langsam lässt sich die Sache mit den SECTIONEN nicht mehr 
ignorieren... Im Moment wird das nur ganz primitiv per "Scopelevel" oder 
"Blocklevel" entschieden, ganz wie man das nennen mag. Also nur an Hand 
der Position im Code, irgendwelche Qualifier ignoriere ich noch bewusst 
um die Komplexität nicht explodieren zu lassen. Den ein oder anderen 
könnte ich aber schon mal einbauen. static zum Beispiel, sollte ja immer 
in DATA_ landen, oder?

Autor: Markus F. (mfro)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Bei "richtigen" Betriebssystemen besteht ein Executable (mindestens) aus 
3 Sections: TEXT, DATA und BSS.

In TEXT gehören m.E. nur Code und (höchstens) Daten, die nur gelesen 
werden (Konstanten).
In DATA gehören (veränderliche) Daten, die einen Initialwert haben.
In BSS gehören (veränderliche) Daten, die beim Programmstart nicht oder 
mit 0 initialisiert werden.

Der Loader (eines "vorsichtigen" Betriebssystems) wird das TEXT-Segment 
(wenn die HW das zulässt) idealerweise in einen Speicherbereich laden, 
der anschließend mittels MMU auf readonly gesetzt wird.
Schreibzugriffe lösen dann einen Fault aus, wenn sie versuchen 
(unabsichtlich oder böswillig), Code zu manipulieren (schließt dann 
natürlich selbstmodifizierenden Code aus, aber das ist meist sowieso 
eine gute Idee).

Autor: S. R. (svenska)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Zu dem üblichen TEXT-DATA-BSS-Tripel kommt oft noch RODATA. Dort liegen 
Konstanten, die im Gegensatz zu TEXT nicht ausführbar und im Gegensatz 
zu DATA nicht schreibbar sein müssen.

Dazu kommt noch der Stack. Lokale Variablen gehören nicht nach DATA, 
sondern auf den Stack.

Autor: Mw E. (Firma: fritzler-avr.de) (fritzler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Stack gehört aber nicht in die exec, den legt das OS zur Laufzeit an 
und wenn er wächst werden mehr Pages per MMU zugemapped.

Autor: fixStackPointer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke @Markus!!!

>Zu dem üblichen TEXT-DATA-BSS-Tripel kommt oft noch RODATA. Dort liegen
>Konstanten, die im Gegensatz zu TEXT nicht ausführbar und im Gegensatz
>zu DATA nicht schreibbar sein müssen.

Ok, RODATA hab ich auch schon mal gehört, gibt nun 4 Sectionen.

>Der Stack gehört aber nicht in die exec, den legt das OS zur Laufzeit an
>und wenn er wächst werden mehr Pages per MMU zugemapped.

? Das ist ja gerade die Frage in welche SECTION? Auf den Stack bedeudet 
es muss per push oder mov auf den stack geschoben werden, das ist 
ausführbarer code und steht in TEXT_.

Autor: S. R. (svenska)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mw E. schrieb:
> Der Stack gehört aber nicht in die exec, den legt das OS
> zur Laufzeit an und wenn er wächst werden mehr Pages
> per MMU zugemapped.

Das ist richtig, setzt aber voraus, dass deine Hardware eine MMU und ein 
OS hat. Das ist nicht überall gegeben.

Das Executable muss nicht wissen, wo der Stack liegt (weil darauf nur 
über den Stackpointer zugegriffen wird), aber der Startup-Code muss den 
Stackpointer initialisieren.

Deswegen muss man den Stack auch im Hinterkopf behalten. :-)

fixStackPointer schrieb:
> Das ist ja gerade die Frage in welche SECTION?

Der Stack ist nur per Stackpointer zugreifbar, liegt also erstmal in 
keiner SECTION. Zumindest nicht, wenn man sich das Executable anschaut.

> Auf den Stack bedeudet es muss per push oder mov auf den stack
> geschoben werden, das ist ausführbarer code und steht in TEXT_.

(a) Nein, man darf auch SP-relativ auf den Stack zugreifen (Stichwort 
"Stack Pointer", "Frame Pointer").
(b) In TEXT stehen auch die Load- und Store-Befehle für Daten. Deswegen 
stehen die Daten selbst aber brav in DATA, RODATA oder BSS - und gehören 
selbst nicht zu TEXT.

Wie gesagt, der Stack muss beim Start korrekt initialisiert werden und 
darf die anderen Sectionen im Speicher nicht überlappen.

Im Executable taucht der Stack nicht auf.
Im Prozessor kann der Stack sein eigenes Segment bekommen (x86) oder 
auch nicht (so ziemlich alle anderen Architekturen).
Im Compiler ist der Stack der Ort für sämtliche lokalen Variablen, 
Register-Spill und andere Dinge.

Autor: Steffen R. (steffen_rose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
fixStackPointer schrieb:
>>Der Stack gehört aber nicht in die exec, den legt das OS zur Laufzeit an
>>und wenn er wächst werden mehr Pages per MMU zugemapped.
>
> ? Das ist ja gerade die Frage in welche SECTION? Auf den Stack bedeudet
> es muss per push oder mov auf den stack geschoben werden, das ist
> ausführbarer code und steht in TEXT_.

???
Der Stack ist extra und die Befehle, diesen zu bedienen, stehen im 
_TEXT.

Außerdem scheinst du bereits Optimierungen einzukalkulieren.
Normalerweise steht eine Konstante in RODATA, wird von da geholt und 
dann genutzt.
Per Optimierung ist sie ggf. bereits Teil des Assemblerbefehls. Da 
beginnen dann bereits die Sektionszuordnungen zu verschwimmen.

Autor: fixStackPointer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Außerdem scheinst du bereits Optimierungen einzukalkulieren.
>Normalerweise steht eine Konstante in RODATA, wird von da geholt und
>dann genutzt.

Jep, es gibt schon ein compilerflag optfor: size | speed
Wollte ich eigentlich erst nicht machen, aber es fallen einem viel zu 
viele Optimierungen ein, die alle zu verwerfen wäre irgendwie schade.

>Im Executable taucht der Stack nicht auf.

Naja, die Push-Pop Orgien werden ja in der executable gefeiert...XD

Vielen dank für eure Anregungen, aber ich glaub ich habs jetzt soweit 
gerafft :D.
Zwischenstand: Bin gerade bei Arrays... :D It's fun :D

Autor: fixStackPointer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Abend :D

Ui...gibt einiges neues:
Arrays sind fast fertig...

Mache jetzt einen "pre-compile" Lauf und ermittle dabei:
-wird eine variable initialisiert?
-wie oft wird sie geschrieben (geplante Optimierung: je mehr Zugriffe, 
desto eher in Register halten)
-wann ist der letzte Zugriff auf die variable (Optimierung: Register 
freigeben)

Damit ergeben sich nun (außer nicht implementierte Qualifier)
alle notwendigen Parameter um die richtige Section auszuwählen.
Da bastel ich gerade noch dran rum.

Desweiteren hab ich bindump.exe entdeckt...
Damit wird natürlich vieles klarer.

Sowas sieht schon gar nicht schlecht aus: relative 
Stackpointer-Adressierung, Stack-Init-Optimierung...
UINT64_T index1;
  UINT64_T index2;
  UINT64_T index3;
  UINT64_T index4;
  UINT64_T index5;
  UINT64_T index6;
  UINT64_T index7;
  UINT64_T index8;
  UINT64_T index9;
  UINT64_T index10;
  UINT64_T index11;
  UINT64_T index12;
  UINT64_T index13;
  UINT64_T index14;
  UINT64_T index15;
  UINT64_T index16;
  
  index1 = 1;
  index2 = 2;
  index3 = 3;
  index4 = 4;
  index5 = 5;
  index6 = 6;
  index7 = 7;
  index8 = 8;
  index9 = 9;
  index10 = 10;
  index11 = 11;
  index12 = 12;
  index13 = 13;
  index14 = 14;
  index15 = 15;
  index16 = 16;
  
  UINT64_T r;

  r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
;   index1 = 1;
mov          RAX          ,           00000001h

;   index2 = 2;
mov          RDX          ,           00000002h

;   index3 = 3;
mov          RCX          ,           00000003h

;   index4 = 4;
mov          R8          ,           00000004h

;   index5 = 5;
mov          R9          ,           00000005h

;   index6 = 6;
mov          RDI          ,           00000006h

;   index7 = 7;
mov          R10          ,           00000007h

;   index8 = 8;
mov          R11          ,           00000008h

;   index9 = 9;
mov          R12          ,           00000009h

;   index10 = 10;
mov          R13          ,           0000000Ah

;   index11 = 11;
mov          R14          ,           0000000Bh

;   index12 = 12;
mov          R15          ,           0000000Ch

;   index13 = 13;
mov          qword ptr [rbp - 8 ]          ,           0000000Dh

;   index14 = 14;
mov          qword ptr [rbp - 16 ]          ,           0000000Eh

;   index15 = 15;
mov          qword ptr [rbp - 24 ]          ,           0000000Fh

;   index16 = 16;
mov          qword ptr [rbp - 32 ]          ,           00000010h

;   r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
imul        RAX          ,           RDX

;   r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
imul        RAX          ,           RCX

;   r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
imul        RAX          ,           R8

;   r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
imul        RAX          ,           R9

;   r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
imul        RAX          ,           RDI

;   r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
imul        RAX          ,           R10

;   r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
imul        RAX          ,           R11

;   r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
imul        RAX          ,           R12

;   r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
imul        RAX          ,           R13

;   r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
imul        RAX          ,           R14

;   r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
imul        RAX          ,           R15

;   r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
imul        RAX          ,           qword ptr [rbp - 8 ]

;   r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
imul        RAX          ,           qword ptr [rbp - 16 ]

;   r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
imul        RAX          ,           qword ptr [rbp - 24 ]

;   r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
imul        RAX          ,           qword ptr [rbp - 32 ]

;   r = index1*index2*index3*index4*index5*index6*index7*index8*index9*index10*index11*index12*index13*index14*index15*index16;
mov          qword ptr [rbp - 40 ]          ,           RAX

Autor: fixStackPointer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So ... lange Nacht hinter mir, aber:
-Sectionen gibt es nun fünf.

Eine Frage dazu, warum gibt es zwei "gleiche Sectionen" pdata und idata?
Beide mit gleichen flags:
-read Only
-Initialized Data

static, const und extern wird nun ausgewertet. in verbindung mit 
scope-und filelevel und dem vorherigen Ermitteln der Initialisierung und 
der Schreibzugriffe versuche ich nun die "LifeTimeDuration" der Objekte 
zu ermitteln...

lg

Autor: fixStackPointer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
code refactoring...

Autor: fixStackPointer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arg... doofes c# oder doofer fixStackPointer:

CopyTo() erstellt keine deep-copy sondern nur eine shadow-copy...

hat mich einen Tag gekostet :(
Egal, weiter geht's :D, frohe Weihnachten!

Autor: Fipo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kennt wer ein Gutes Tutorial für avx 512?

Autor: Mw E. (Firma: fritzler-avr.de) (fritzler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guck dir die Intel Intrinsics an und machs in C:
https://software.intel.com/sites/landingpage/IntrinsicsGuide/#techs=AVX_512
Im makefile dann -native angeben mit er auch AVX nutzt.

Mit AVX2 hab ich meinen Mandelbrotzeichner beschleunigt.

S. R. schrieb:
> Mw E. schrieb:
>> Der Stack gehört aber nicht in die exec, den legt das OS
>> zur Laufzeit an und wenn er wächst werden mehr Pages
>> per MMU zugemapped.
>
> Das ist richtig, setzt aber voraus, dass deine Hardware eine MMU und ein
> OS hat. Das ist nicht überall gegeben.

Ja gut, aber wo wir hier über x86 und eigen gebautem Compiler reden hab 
ich ein unterliegendes OS sowie eine MMU angenommen ;)

Autor: S. R. (svenska)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mw E. schrieb:
> Ja gut, aber wo wir hier über x86 und eigen gebautem Compiler reden hab
> ich ein unterliegendes OS sowie eine MMU angenommen ;)

Und vollkommen zurecht. :-)

fixStackPointer schrieb:
> Wollte ich eigentlich erst nicht machen, aber es fallen einem viel zu
> viele Optimierungen ein, die alle zu verwerfen wäre irgendwie schade.

Hast du dich mal mit dem Aufbau klassischer Compiler beschäftigt, also 
SSA und sowas? In den Büchern stehen die viele grundlegende 
Optimierungen schon drin. ;-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.