2016-05-08 12 views
0

Ich habe eine Klasse in meiner cpp-Datei.Nasm, C++, passendes Klassenobjekt

class F{ 
private: 
    int id; 
    float o; 
    float p; 
    float s; 
    static int next; 
public: 
    F(double o, double s = 0.23, double p = 0.0): 
    id(next++), o(o), 
    p(p), s(s){} 
}; 

int F::next = 0; 

extern "C" float pod(F f); 

int main(){ 
    F bur(1000, 0.23, 100); 
    pod(bur); 
    return 0; 
} 

und ich versuche bur Klasse Objekt zu übergeben pod funktionieren, die in meiner asm-Datei definiert ist. Allerdings habe ich große Probleme, Werte von diesem Klassenobjekt zu bekommen.

In asm-Programm Ich habe 0.23 in XMM1, 100 in XMM2 aber ich kann nicht finden, wo 1000 gespeichert ist.

Antwort

1

Ich weiß nicht, warum Sie 100 in xmm2 sehen, ich vermute, dass das völlig conincidence ist. Der einfachste Weg zu sehen, wie Ihre Struktur übergeben wird, besteht darin, den C++ - Code zu kompilieren.

Mit cruft entfernt, mein Compiler tut dies:

main: 
.LFB3: 
     .cfi_startproc 
     subq $8, %rsp 
     .cfi_def_cfa_offset 16 
     movl _ZN1F4nextE(%rip), %edi # load F::next into edi/rdi 
     movq .LC3(%rip), %xmm0   # load { 0.23, 100 } into xmm0 
     leal 1(%rdi), %eax    # store rdi + 1 into eax 
     movl %eax, _ZN1F4nextE(%rip) # store eax back into F::next 
     movabsq $4934256341737799680, %rax # load { 1000.0, 0 } into rax 
     orq  %rax, %rdi     # or rax into pre-increment F::next in rdi 
     call pod 
     xorl %eax, %eax 
     addq $8, %rsp 
     .cfi_def_cfa_offset 8 
     ret 
.LC3: 
     .quad 4497835022170456064 

Die Konstante 4497835022170456064 ist 3E6B851F42C80000 in hex, und wenn Sie die wichtigsten vier Bytes zu buchen (3E6B851F), diese 0.23 ist, wenn sie als einzige interpretiert Genauigkeit float, und die niedrigstwertigen vier Bytes() sind 100.0.

Ähnlich sind die höchstwertigen vier Bytes der Konstante 4934256341737799680 (hex 447A000000000000) 1000.0.

So bur.id und bur.o geben werden in rdi und bur.p und bur.s sind in xmm0 weitergegeben. Der Grund dafür ist in der x86-64 abi reference dokumentiert. Da die ersten fwo-Felder klein genug sind, vom gemischten Typ und einer von ihnen ganzzahlig sind, werden sie in einem allgemeinen Register übergeben (rdi ist das erste allgemeine Parameterregister), weil die nächsten zwei Felder beide float sind Sie werden in einem SSE-Register übergeben.

+0

Ihr Code wurde mit Optimierungen kompiliert (keine zusätzlichen Lasten und Speicher). Ich vermute, dass das OP keine Optimierungen verwendet hat und _XMM2_ vorübergehend vor dem 'Call Pod' verwendet wurde. Er dachte wahrscheinlich, dass es ein Teil der Parameter war. –

1

Sie möchten sich die Calling-Convention-Compilierung von Agners here ansehen. Je nach Compiler, Betriebssystem und ob Sie in 32 oder 64 Bit sind, können verschiedene Dinge passieren. (siehe Tabelle 5, Kapitel 7).

Für 64bits zum Beispiel Linux, da Sie unterschiedliche Werte Objekt enthält, die R Fall scheint (siehe Tabelle 6) anzuwenden: die Größe

gesamte Objekt in Integer-Register übertragen und/oder XMM-Register, wenn ist nicht größer als 128 Bits, sonst auf dem Stack. Jeder 64-Bit-Teil des Objekts wird in ein XMM-Register übertragen, wenn es nur float oder double enthält, oder in ein Integer-Register, wenn es Integer-Typen oder gemischte Integer und Float enthält. Zwei aufeinanderfolgende Floats können in die untere Hälfte eines XMM-Registers gepackt werden.

In Ihrem Fall passt die Klasse in 128 Bits. Das Experiment von @CharlesBailey veranschaulicht dieses Verhalten. Gemäß der Konvention

... oder in einem Integer-Register, wenn es Integer-Typen oder gemischte Integer und Float enthält. Zwei aufeinanderfolgende Floats können in die untere Hälfte eines XMM-Registers gepackt werden.Beispiele: int und float: RDI.

erste int Register rdi sollte id und o halten, wo xmm0 sollte p und s halten.

Das Sehen von 100 innerhalb von xmm2 könnte ein Nebeneffekt der Initialisierung sein, da diese als Doppel an den Strukturkonstruktor übergeben wird.