Thread: C->C++ conversion

  1. #1
    Registered User
    Join Date
    Oct 2009
    Posts
    46

    C->C++ conversion

    How to convert the code below to use std::vector and std::copy. Is it even possible? I'm just having some fun and trying to convert a piece of my code to c++ style.

    Code:
    // Just an example, missing some stuff.
    std::string vendor; // already in c++
    unsigned int registers[4];
    
              asm volatile
              (
                "pushq %%rbx\n\t"
                "cpuid\n\t"
                "movq %%rax, (%1)\n\t"
                "movq %%rbx, 4(%1)\n\t"
                "movq %%rdx, 8(%1)\n\t"
                "movq %%rcx, 12(%1)\n\t"
                "popq %%rbx\n\t"
               :
               : "a"(cpuidOperation), "S"(registers)
              );
    
    memcpy((void *)vendor.c_str(),&registers[1],3*sizeof(unsigned int));
    This is what I have done so far, but I'm a bit stuck in std::copy.

    Code:
    std::string vendor;
    std::vector<unsigned int> registers_cpuinfo;
    registers_cpuinfo.reserve(4);
    
              asm volatile
              (
                "pushq %%rbx\n\t"
                "cpuid\n\t"
                "movq %%rax, (%1)\n\t"
                "movq %%rbx, 4(%1)\n\t"
                "movq %%rdx, 8(%1)\n\t"
                "movq %%rcx, 12(%1)\n\t"
                "popq %%rbx\n\t"
               :
               : "a"(cpuidOperation), "S"(&registers_cpuinfo)
              );
    
     std::copy(registers_cpuinfo.begin(), registers_cpuinfo.begin()
                     + 3*sizeof(unsigned int),vendor.begin()); ??
    Thanks for any hints.

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Assuming you don't want to touch the asm code, the code you want follows. I've highlighted the bits I changed that you got wrong.
    Code:
    std::string vendor;
    std::vector<unsigned int> registers_cpuinfo;
    vendor.resize(4);
    registers_cpuinfo.resize(4);    // reserve is insufficient
    
              asm volatile
              (
                "pushq %%rbx\n\t"
                "cpuid\n\t"
                "movq %%rax, (%1)\n\t"
                "movq %%rbx, 4(%1)\n\t"
                "movq %%rdx, 8(%1)\n\t"
                "movq %%rcx, 12(%1)\n\t"
                "popq %%rbx\n\t"
               :
               : "a"(cpuidOperation), "S"(&registers_cpuinfo[0])
              );
    
     
     std::copy(registers_cpuinfo.begin(), registers_cpuinfo.begin() + 3,vendor.begin());
    If the destination - vendor.begin() in your case - is not an insert iterator (which vendor.begin() is not), then std::copy() assumes the container has enough elements already allocated to accept the copy. The vendor.resize(4) ensures that.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  3. #3
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    The first code block is invalid. You aren't allowed to copy data to the address provided to you by `std::string::c_str()'.

    The second code block is crazy. What you are trying to do in the second code block will almost certainly fail because the `copy' operation will truncate the values.

    You are probably better off punning the `registers' to a `char *', iterating over the memory to check for embedded `null' values, changing any `null' values to ` ' (space), and assigning the constant character to the `std::string' instance using the assignment operator. (You'll need an extra byte for `registers' to store the eventual `null' terminator.)

    You will not need the otherwise useless `std::vector' or the `std::copy' that way.

    I have to ask, it is the only reason I responded, what dialect is that?

    [Edit]
    I can't image than the source grumpy posted is right for the same reason. The `std::copy' function is simply not a fancy alias for `std::memcpy'. It may, for a particular implementation, work, but I doubt it.
    [/Edit]

    Soma
    Last edited by phantomotap; 03-16-2010 at 03:43 AM.

  4. #4
    Registered User
    Join Date
    Oct 2009
    Posts
    46
    The first code block is invalid. You aren't allowed to copy data to the address provided to you by `std::string::c_str()'.
    I see what you mean. c_str() returns const char *. In this case it works albeit its not correct.

    The second code block is crazy. What you are trying to do in the second code block will almost certainly fail because the `copy' operation will truncate the values.
    I'm not really aware of how stl copy works. (not yet)

    You are probably better off punning the `registers' to a `char *', iterating over the memory to check for embedded `null' values, changing any `null' values to ` ' (space), and assigning the constant character to the `std::string' instance using the assignment operator. (You'll need an extra byte for `registers' to store the eventual `null' terminator.)
    This does not goes well on what I want to do. Anyway thanks for the idea.

    I have to ask, it is the only reason I responded, what dialect is that?
    What are you referring to? the gcc inline assembly code?

    I really have to start playing with c++!

    Thanks for all the tips grumpy and phantomotap.
    Last edited by sugarfree; 03-16-2010 at 05:25 AM.

  5. #5
    Registered User
    Join Date
    Jan 2010
    Posts
    412
    Here's an example on how you could do it with an uint vector.
    It's in intel assembler syntax though. I have no idea how to convert it to AT&T, but hopefully you'll get the idea.
    Code:
    const std::string GetVendorName_uint()
    {
    	std::vector<unsigned int> data(5, 0); // 1 extra element to null-terminate the string
    	unsigned int* p = &data[0];
    
    	__asm
    	{
    		pushad
    		mov eax, 0
    		cpuid
    		mov esi, p
    		mov [esi], eax
    		mov [esi+4], ebx
    		mov [esi+8], edx
    		mov [esi+12], ecx
    		popad
    	}
    
    	char* str = reinterpret_cast<char*>(&data[1]); // skip eax
    	return std::string(str);
    }

  6. #6
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    In this case it works albeit its not correct.
    No. It doesn't.

    It may appear to work under these circumstances for your environment. I doubt even that much.

    This does not goes well on what I want to do.
    The first code block attempts to do part of what I suggested.

    You can't do what you seem to want to do with the tools you are trying to do it with.

    It looks to me as if you are trying to get the vendor ID string into a `std::string' variable in a very round about or illegal fashion. (This can be done, for x86, far simpler.) Is this what you are trying to do? If not, maybe you should describe in words what you are trying to do.

    the gcc inline assembly code?
    That's GCC/GAS inline assembler? Wow. There is a couple of features there I haven't seen before.

    Soma

  7. #7
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Here's an example on how you could do it with an uint vector.
    That should work, but I still wonder why you would want to pay for the "ACDD Dance" of `std::vector<???>' when you wind up by punning the data at the relevant address anyway?!

    Also, you don't need to explicitly store the value of `EAX' after `CPUID' returns if you are only going to throw it away.

    Soma

  8. #8
    Registered User
    Join Date
    Jan 2010
    Posts
    412
    Quote Originally Posted by phantomotap View Post
    That should work, but I still wonder why you would want to pay for the "ACDD Dance" of `std::vector<???>' when you wind up by punning the data at the relevant address anyway?!
    No idea really, I'm just answering the question

    Also, you don't need to explicitly store the value of `EAX' after `CPUID' returns if you are only going to throw it away.
    Yes I know. But I included it just to show how to make a string from a vector where it's included.
    I noticed the "cpuidOperation" variable in the OPs post so I'm assuming he wants to keep eax for the other cpuid calls besides vendor name.

  9. #9
    Registered User
    Join Date
    Oct 2009
    Posts
    46
    Quote Originally Posted by phantomotap View Post
    No. It doesn't.

    It may appear to work under these circumstances for your environment. I doubt even that much.
    It works, at least in my conditions. May fail in other ones, I don't disagree there.


    You can't do what you seem to want to do with the tools you are trying to do it with.

    It looks to me as if you are trying to get the vendor ID string into a `std::string' variable in a very round about or illegal fashion. (This can be done, for x86, far simpler.) Is this what you are trying to do? If not, maybe you should describe in words what you are trying to do.
    In this specific case, I'm just getting the vendor name, but the assembly code is supposed to be reused, to get other features of the CPU. Feel free to explain how I can do this in other ways.


    That's GCC/GAS inline assembler? Wow. There is a couple of features there I haven't seen before.
    Yep


    Also, you don't need to explicitly store the value of `EAX' after `CPUID' returns if you are only going to throw it away.
    Yes I know. But I included it just to show how to make a string from a vector where it's included.
    I noticed the "cpuidOperation" variable in the OPs post so I'm assuming he wants to keep eax for the other cpuid calls besides vendor name.
    Exactly!


    That should work, but I still wonder why you would want to pay for the "ACDD Dance" of `std::vector<???>' when you wind up by punning the data at the relevant address anyway?!
    What is punning? English is not my native language.

  10. #10
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Honestly with embedded asm I'd just keep the C style. It's clearer and you aren't paying for dynamic allocation of the vector.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  2. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  3. Header File Question(s)
    By AQWst in forum C++ Programming
    Replies: 10
    Last Post: 12-23-2004, 11:31 PM
  4. Do I have a scanf problem?
    By AQWst in forum C Programming
    Replies: 2
    Last Post: 11-26-2004, 06:18 PM
  5. Creation of Menu problem
    By AQWst in forum C Programming
    Replies: 8
    Last Post: 11-24-2004, 09:44 PM