Toon posts:

[C++/asm] CPUID uitlezen gaat mis

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik probeer met c++ de cpu vendor te achterhalen en deze weg te schrijven naar het scherm. Helaas wil dit maar niet lukken.

Ik heb onderstaande code voor FreePascal omgebouwd tot c++
Code in FreePascal
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Program CPUVendor;

Var
   VEN: string[12];

Begin
   {Call CPUID}
   Asm
      {EAX determines function}
      mov eax,$0
      cpuid
      mov [VEN],12 {String length}
      mov [VEN + 1],ebx
      mov [VEN + 5],edx
      mov [VEN + 9],ecx
   {These registers are modified}
   End ['eax','ebx','ecx','edx'];
   {Display results}
   writeln('CPU Vendor: ',VEN);
End;


Bron: http://www.paradicesoftware.com/specs/cpuid/index.htm

Code naar C++
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <string>

using namespace std;

int main ()
{
               string cpuInfo;
    __asm
        {
        mov eax, 0
        cpuid
        //mov ebx, cpuInfo
        //mov edx, cpuInfo
        mov ecx, cpuInfo
        }
    

    cout << "CPU -> " << cpuInfo;
    return 0;
}


Zie ik iets over het hoofd. Om te compilen gebruik ik Visual C++ 6.0 op Win Xp Pro Sp1

Ik heb wat code in comments gezet puur om testen maar ik krijg dus gewoon helemaal niks. Kan iemand me verder helpen.

Als ik iets belangrijks heb weggelaten in mijn post dan hoor ik het wel.

[ Voor 9% gewijzigd door Verwijderd op 25-02-2004 01:08 ]


  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 22-05 13:09
cpuInfo is een object van de classe string. Daar kan je niet zomaar met mov tekens inzetten. Gebruik daarvoor een char[13] en zet op stringInfo[12] een '\0' om de null-terminated string af te sluiten.

Ook had je de argumenten van de mov instructies omgedraaid.

Verwijderd

Topicstarter
matthijsln schreef op 25 februari 2004 @ 01:26:
cpuInfo is een object van de classe string. Daar kan je niet zomaar met mov tekens inzetten. Gebruik daarvoor een char[13] en zet op stringInfo[12] een '\0' om de null-terminated string af te sluiten.

Ook had je de argumenten van de mov instructies omgedraaid.
Hm kun je me een voorbeeld geven van hoe je dat precies bedoelt met char.

En die mov statements moeten zo. De eerste is gebaseerd op de A&T syntax. Die begrijpt vc niet. Die gebruikt namelijk Intel ASM.
Toch ?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je asm zelf ziet er idd goed uit, maar zoals matthijsln al zegt kun je niet zomaar een waarde assignen aan een std::string. Nogal logisch, een string is hoogstwaarschijnlijk een klasse met daarin een char *, even kort door de bocht zoiets dus:

C++:
1
2
3
4
struct string
{
    char * buffer;
};


Wat jij nu doet is de 4 bytes uit ecx kopiëren over de string, met als resultaat dat string::buffer de waarde van ecx krijgt (oftewel, als ecx 123 wordt, dan wijst buffer dus naar de char op geheugenlocatie 123. Uiteraard heeft die geheugenlocatie helemaal niets te maken met de string die cpuinfo retourneert ;))

Wat je nodig hebt is een stukje geheugen waar je de bytes direct in kunt zetten. Een char array dus :)

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream> 

int main () 
{ 
    char cpuinfo[13] = { }; 

    __asm 
    {
        push ebx
        xor eax, eax 
        cpuid 
        mov dword ptr [cpuinfo], ebx
        mov dword ptr [cpuinfo + 4], edx
        mov dword ptr [cpuinfo + 8], ecx
        pop ebx
    } 

    std::cout << cpuinfo << std::endl; 
}


.edit: die dword ptr is ervoor omdat cpuinfo een char (8 bits) is, terwijl de registers die je wegschrijft natuurlijk 32 bits zijn

.edit2: oh, nog iets, de waarde van ebx moet je bewaren omdat dat een register is die je niet zelf mag veranderen. Ik weet trouwens niet hoe VC++ hiermee omgaat eigenlijk, of ie zelf kijkt welke registers veranderd zijn of niet.
.edit3: ah kijk, ik had die push/pop ebx en cpuid uitgecomment, en gekeken naar de gegenereerde assembly van main, en toen gaf de compiler zelf geen push/pop ebx aan het begin en eind van de functie. Als ik vervolgens de cpuid uncomment (maar niet mijn eigen push/pop ebx), dan voegt ie ze zelf toe, wat betekent dat ie zelf bijhoudt welke registers zijn aangepast _o_. Met mijn eigen push/pop ebx staan ze dubbelop, dus je kunt ze beter weghalen (ik laat ze hier even staan anders wordt deze edit zo onduidelijk ;))

[ Voor 44% gewijzigd door .oisyn op 25-02-2004 02:06 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • El Psycho
  • Registratie: September 2002
  • Laatst online: 13-05 13:40
hij bedoelt dat je ipv een
code:
1
string cpuInfo

een
code:
1
char cpuInfo[13]

moet gebruiken, oftewel een array van 13 characters. Het laatste character (da's dus cpuInfo[12]) moet je op charachter '\0' of 0 zetten om de string af te sluiten.

verder lijkt het me dat wat die assembler code doet het volgende is:
code:
1
2
3
4
      mov [VEN],12 {String length}  //zet het getal 12 op positie 0 van de string
      mov [VEN + 1],ebx     // zet inhoud register ebx op posities 1 ..  4
      mov [VEN + 5],edx     // zet inhoud register edx op posities 5 ..  8
      mov [VEN + 9],ecx     // zet inhoud register ecx op posities 9 .. 12


pascal werkt met strings waarbij de lengte op positie 0 staat, c niet dus die eerste instructie hoeft niet en de rest moet één character eerder

jij zou het dus als volgt moeten doen:
code:
1
2
3
      mov [cpuInfo],ebx     // zet inhoud register ebx op posities 0 ..  3
      mov [cpuInfo + 4],edx     // zet inhoud register edx op posities 4 ..  7
      mov [cpuInfo + 8],ecx     // zet inhoud register ecx op posities 8 .. 11


alleen dan met de juiste assembler syntax die ik ff niet weet :)

[edit: veel te laat |:( ]

[ Voor 4% gewijzigd door El Psycho op 25-02-2004 01:55 . Reden: was te laat ]


Verwijderd

Topicstarter
.oisyn schreef op 25 februari 2004 @ 01:51:
Je asm zelf ziet er idd goed uit, maar zoals matthijsln al zegt kun je niet zomaar een waarde assignen aan een std::string. Nogal logisch, een string is hoogstwaarschijnlijk een klasse met daarin een char *, even kort door de bocht zoiets dus:

C++:
1
2
3
4
struct string
{
    char * buffer;
};


Wat jij nu doet is de 4 bytes uit ecx kopiëren over de string, met als resultaat dat string::buffer de waarde van ecx krijgt (oftewel, als ecx 123 wordt, dan wijst buffer dus naar de char op geheugenlocatie 123. Uiteraard heeft die geheugenlocatie helemaal niets te maken met de string die cpuinfo retourneert ;))

Wat je nodig hebt is een stukje geheugen waar je de bytes direct in kunt zetten. Een char array dus :)

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream> 

int main () 
{ 
    char cpuinfo[13] = { }; 

    __asm 
    {
        push ebx
        xor eax, eax 
        cpuid 
        mov dword ptr [cpuinfo], ebx
        mov dword ptr [cpuinfo + 4], edx
        mov dword ptr [cpuinfo + 8], ecx
        pop ebx
    } 

    std::cout << cpuinfo << std::endl; 
}


.edit: die dword ptr is ervoor omdat cpuinfo een char (8 bits) is, terwijl de registers die je wegschrijft natuurlijk 32 bits zijn

.edit2: oh, nog iets, de waarde van ebx moet je bewaren omdat dat een register is die je niet zelf mag veranderen. Ik weet trouwens niet hoe VC++ hiermee omgaat eigenlijk, of ie zelf kijkt welke registers veranderd zijn of niet.
Thanks dit werkt perfect. Krijg nog wel 3 rare tekens aan het eind.
Maar kijk ik morgen naar verplicht slapen nu :(

Thx voor je hulp.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

Vreemd, hier werkt het wel goed, ik gebruik VC++ 7.1

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>

int main ()  
{  
    char cpuinfo[13];  

    __asm  
    { 
       // push ebx 
        //xor eax, eax  
        mov eax,0
        cpuid  
        mov dword ptr cpuinfo[0], ebx
        mov dword ptr cpuinfo[4], edx 
        mov dword ptr cpuinfo[8], ecx 
       // pop ebx 
    }  

    std::cout << cpuinfo << std::endl;
}


Gebruik nu dit en het werkt.
Alleen die rare tekens op het einde na dan.
Zelfde gebeurt als ik de code exact overneem.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ook als je mijn code exact overneemt? Ik heb namelijk achter die declaratie van cpuinfo[13] nog = { }; staan, dat zorgt ervoor dat de hele array op 0 geinitialiseerd wordt (dat is wel noodzakelijk, aangezien het laatste teken van een string het 0 character moet zijn)

(xor eax, eax is trouwens hetzelfde als mov eax, 0 ;))

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
.oisyn schreef op 25 februari 2004 @ 02:26:
Ook als je mijn code exact overneemt? Ik heb namelijk achter die declaratie van cpuinfo[13] nog = { }; staan, dat zorgt ervoor dat de hele array op 0 geinitialiseerd wordt (dat is wel noodzakelijk, aangezien het laatste teken van een string het 0 character moet zijn)

(xor eax, eax is trouwens hetzelfde als mov eax, 0 ;))
code:
1
cpuinfo[13] = { };

Werkt niet in VC 6

Maar je bracht me op een idee.
code:
1
char cpuinfo[13] ={0};


Werkt wel en voila tekens zijn weg.
Mja zou je wel willen zoenen ;)

ben slecht thuis is Asm dus ik had geen idee wat xor eax, eax precies deed.
Zo is het voor mij op moment duidelijker.

Noob question weer. Waar kun je de asm code terug vinden die vc uit :r

[ Voor 5% gewijzigd door Verwijderd op 25-02-2004 02:32 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:03
off-topic:
.oisyn schreef op 25 februari 2004 @ 02:26:
(xor eax, eax is trouwens hetzelfde als mov eax, 0 ;))
Maar xor eax, eax is beter, omdat je dan niet hoeft na te denken of de operands in Intel- of AT&T-volgorde moeten staan. ;)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

Mja VC6 is een kutcompiler, gooi die maar de deur uit :P

Soultaker: bovendien is xor eax, eax maar 1 byte, itt de 5 bytes van mov eax, 0 ;)

[ Voor 46% gewijzigd door .oisyn op 25-02-2004 02:39 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op 25 februari 2004 @ 02:31:
Noob question weer. Waar kun je de asm code terug vinden die vc uit :r
kun je ergens instellen in je project options, maar makkelijker is even je project runnen door op ctrl-f10 te drukken als je met de cursor in de juiste functie staat, en dan even het disassembly window te openen (staat ergens in het Debug menu)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-05 16:53
Verwijderd schreef op 25 februari 2004 @ 02:31:
Noob question weer. Waar kun je de asm code terug vinden die vc uit :r
Je kunt ergens in de project options instellen dattie een list file moet genereren.

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.

Pagina: 1