[assembly] gcc error bij inline assembly code in c++

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • janwillemCA
  • Registratie: Mei 2014
  • Laatst online: 09:12
hallo,

Tijdens het compileren met GCC van dit stukje code:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <sys/time.h>
#include <time.h>
#include <stdio.h>
#include <iostream>
#include <stdint.h>
#include <unistd.h>

using namespace std;

int _tmain(int argc, char* argv[])
{       
        while(1)
        {       
                int64_t unsigned BeginClock = 0;
                int64_t unsigned EndClock = 0;
                int64_t unsigned Speed = 0;
                
                asm ("RDTSC;"
                     "MOV DWORD PTR SS:[BeginClock], %EAX;"
                     "MOV DWORD PTR SS:[BeginClock+4], %EDX;");
                
                sleep(1000);
                
                asm ("RDTSC;"
                     "MOV DWORD PTR SS:[EndClock], %EAX;"
                     "MOV DWORD PTR SS:[EndClock+4], %EDX;");
                
                Speed = (EndClock - BeginClock); 
                Speed = Speed / (1000000 * (1000/1000));
                
                printf ("CPU Frequentie: "); //<< Speed << " MHZ"; //spreekt voorzichzelf
        }
}


Krijg ik de error mee:

code:
1
2
3
4
5
6
janwillem@linux-mwmd:~/Documents> g++ CPUSpeed.cpp -g -o cpuspeed
CPUSpeed.cpp: Assembler messages:
CPUSpeed.cpp:20: Error: junk `PTR SS:[BeginClock]' after expression
CPUSpeed.cpp:20: Error: junk `PTR SS:[BeginClock+4]' after expression
CPUSpeed.cpp:26: Error: junk `PTR SS:[EndClock]' after expression
CPUSpeed.cpp:26: Error: junk `PTR SS:[EndClock+4]' after expression


Ik heb al verschillende google hits van deze error bekeken, maar ik wordt er nog niet heel veel wijzer uit. Ziet iemand hier wat & waar het fout gaat?

Mvg,

Jan Willem

Unix is simple. It just takes a genius to understand its simplicity


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 01:41
Ten eerste: int64_t unsigned :? Dat compileert niet!

Ten tweede: je kunt in inline assembly niet zomaar aan lokale variabelen refereren, want die bestaan op dat niveau niet meer (het zijn dan locaties op de stack, of registers, of een combinatie daarvan).

Ten derde: GCC genereert op de meeste platforms assembly in AT&T syntax, niet Intel syntax.

Om te zien waar het mis gaat, kun je GCC de gegenereerde assembly code naar een bestand laten schrijven. Dan zul je zien dat inline assembly niet "speciaal" is; het is geween tekst die letterlijk in de assembly code ingevoegd wordt voordat die naar de assembler gestuurd wordt. Het commando daarvoor is:
g++ -S CPUSpeed.cpp

De gegenereerde assembly staat dan in CPUSpeed.s.

edit:
Als je wil weten hoe het dan wel moet: je hebt grofweg twee opties. De eerste is om de gewenste functionaliteit in een functie te stoppen en die functie in z'n geheel in assembly te implementeren. Het voordeel daarvan is dat je geen C/C++ hoeft te mengen met assembly. De tweede optie (die hier meer geschikt is) is het gebruik van GCC's extended assembly syntax waarbij je meer controle hebt over hoe de assembly code samenwerkt met de omringende C/C++ code. Het voordeel daarvan is dat de compiler agressiever kan optimaliseren.

Op de gelinkte pagina komt ook een voorbeeld met de RDTSC instructie voorbij, dus ik zal die code hier niet herhalen. Zorg wel dat je de hele pagina doorleest zodat je ook begrijpt hoe het precies werkt.

[ Voor 91% gewijzigd door Soultaker op 05-04-2015 20:15 ]


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 14-10 00:53
Je weet dat deze instructie niet zonder meer gebruikt kan worden als betrouwbare bron voor timing?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • janwillemCA
  • Registratie: Mei 2014
  • Laatst online: 09:12
Ah ja, ik had al gelezen over die tweede optie inderdaad!
Dan zal ik daar naar kijken, zoals jullie misschien wel merken ben ik redelijk nieuw in het hele assembly programmeren, vandaar dat er hier en daar wat dingetjes niet kloppen.

Unix is simple. It just takes a genius to understand its simplicity


Acties:
  • 0 Henk 'm!

  • janwillemCA
  • Registratie: Mei 2014
  • Laatst online: 09:12
Klopt, maar het is om de cpu frequentie voor een hobby project uit te lezen, dus dat het niet helemaal betrouwbaar is neem ik voor lief.

Unix is simple. It just takes a genius to understand its simplicity


Acties:
  • 0 Henk 'm!

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Je hebt hier gelukkig helemaal geen inline assembly voor nodig. GCC export deze (en verschillende andere) instructies gewoon als intrinsics.

C:
1
2
3
4
5
6
7
8
9
10
11
12
#include <x86intrin.h>
#include <stdint.h>
#include <unistd.h>

int main() {
    uint64_t start = _rdtsc();
    usleep(1);
    uint64_t end = _rdtsc();
    uint64_t freq = (1000000 * (1000/1000));
    printf("%llu\n", (end - start) / freq);
    return 0;
}

Acties:
  • 0 Henk 'm!

  • janwillemCA
  • Registratie: Mei 2014
  • Laatst online: 09:12
Top oplossing, veel beter. Bedankt!

Unix is simple. It just takes a genius to understand its simplicity


Acties:
  • 0 Henk 'm!

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Overigens "1000/1000" slaat natuurlijk nergens op ;) maar goed, daar ging je vraag niet over :)
Pagina: 1