asm to c++?

Pages: 12
@Jonnin,@JlBorges,@Seeplusplus thanks for the help and wealth of info you offered, truly this is great stuff, but I have asome questions I hope you'd clarify from the above snippets.

@JlBorges:
1
2
3
4
5
6
7
8
9
10
template < typename T >
typename std::enable_if< std::is_integral<T>::value, std::string_view >::type hex_str_view( T value )
{
    static char buffer[128] ;
    const auto [ ptr, ec ] = std::to_chars( buffer, buffer+sizeof(buffer), value, 16 ) ;
    
return { buffer, std::size_t(ptr-buffer) } ;
//{ buffer, std::size_t(ptr-buffer) } what is this construct, what type does this function return? 
//is this equivalent to std::make_pair(char*,std::size_t)?
}


@Seeplus
1
2
3
4
5
6
for (; w; w >>= 4)//please elaborate the workings of this loop.
		*itr++ = digits[w & 0x0f];//??


return {rc.data(), std::to_chars(rc.data(), rc.data() + rc.size(), w, 16).ptr};
//I can't find any std::string constructor with this signature. 



thanks for those stats now I'm really interested in this std::to_chars but this confuses me:
1
2
3
4
5
6
7
8
//from c++ reference:

//Return value
//On success, returns a value of type to_chars_result such that ec equals value-initialized 
//std::errc and ???ptr is the one-past-the-end pointer of the characters written??. Note that the string is not NUL-terminated.

//how do you use a ptr that is just beyond the last char to initialize a new string?? 
//can this read to access violation given that the string isn't null terminated? 
Last edited on
> what type does this function return?

1
2
template < typename T >
typename std::enable_if< std::is_integral<T>::value, std::string_view >::type hex_str_view( T value )


This function is available if and only if T is an integral type; it returns a std::string_view

std::enable_if: https://en.cppreference.com/w/cpp/types/enable_if
std::is_integral: https://en.cppreference.com/w/cpp/types/is_integral
std::string_view: https://en.cppreference.com/w/cpp/string/basic_string_view


> return { buffer, std::size_t(ptr-buffer) } ; // what is this construct

It constructs a std::string_view using constructor (3)
https://en.cppreference.com/w/cpp/string/basic_string_view/basic_string_view
The view contains the first std::size_t(ptr-buffer) characters in buffer
With C++20, the code is simpler; we could have used constructor (5) and written:
return { buffer, ptr } ;

Uniform initialisation: https://www.stroustrup.com/C++11FAQ.html#uniform-init


> how do you use a ptr that is just beyond the last char to initialize a new string??
> //can this read to access violation given that the string isn't null terminated?

The pointer is used as an iterator; the characters in the range are up to the character just before the one pointed to by ptr. ptr is the iterator to the end of the range; the end of a range is defined as the element following the last valid element.

With iterators, a null-termination isn't required or used; the end of the sequence of characters is specified by the iterator to the end of the range.
1
2
for (; w; w >>= 4)//please elaborate the workings of this loop.
		*itr++ = digits[w & 0x0f];//?? 


w is the number. w & 0x0f only gives the lowest 4 bits (a number in the range 0 - 15). This is used as the index into digits to obtain the required hex digit from the string

w >>= 4 right shifts w by 4 bits (divide by 16). The lowest 4 bits of w are now the next digit to obtain.

This cycle is repeated while w is not zero. Hence you get the required hex digits from low-order to high-order. As we want these in the other order, itr is a reverse iterator.

 
return {rc.data(), std::to_chars(rc.data(), rc.data() + rc.size(), w, 16).ptr};


This is construct from a range. See option 7 http://www.cplusplus.com/reference/string/string/string/
Last edited on
1
2
3
4
5
6
7
8
9
10
11
template <typename T>
std::string toHex2(T w) {
	static const char* const digits {"0123456789ABCDEF"};
	std::string rc(sizeof(T) << 1, '0');
	auto itr {rc.rbegin()};

	for (; w; w >>= 4)
		*itr++ = digits[w & 0x0f];

	return itr == rc.rbegin() ? "0" : std::string(itr.base(), rc.end());
}


This is not a good idea; it will engender undefined behaviour if the template is instantiated with a signed integer type and a negative value is passed (in for (; w; w >>= 4), w would never become equal to zero).
Test it: http://coliru.stacked-crooked.com/a/47366b10226693f9
Yes, well this is why thorough testing is needed! If T is signed, then the shift right will bring in 1's from the MSB due to sign extension.
Last edited on
We can use the corresponding unsigned integer type:
for( std::make_unsigned_t<I> uw = w ; uw ; uw >>= 4) *itr++ = digits[ uw & 0x0f ];
Yes. You're just beaten me too it! :)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <string>
#include <iterator>
#include <type_traits>

template <typename T>
typename std::enable_if_t<std::is_integral_v<T>, std::string>
toHexStr(T w) {
	static const char* const digits {"0123456789ABCDEF"};

	std::string rc(sizeof(T) << 1, '0');
	auto itr {rc.rbegin()};

	for (auto wu {std::make_unsigned_t<T>(w)}; wu; wu >>= 4)
		*itr++ = digits[wu & 0x0f];

	return itr == rc.rbegin() ? "0" : std::string(itr.base(), rc.end());
}

int main()
{
	std::cout << toHexStr(-4) << '\n';
	std::cout << toHexStr(4) << '\n';
}



FFFFFFFC
4

Last edited on
Thanks for the clarifications you've provided, I really appreciate.
I've been going through the references provided and I'm still getting more questions, for example:

Assume that those functions below are defined somewhere else and they do exactly what their names imply.
1
2
3
4
5
6
7
8
9
int main()
{
    std::string Mssg = acquire_message();//gets a message from somewhere
    std::string_view mssg_view{Mssg.begin(),Mssg.end()}; //valid view of the message
    
    Mssg = "different message"//malicious code changed the message
    
    use_mssg_view(mssg_view);//does this view still contain the original message or the corrupted message
}



for std::to_char what is that magic number 16 you seem to be using because from
https://en.cppreference.com/w/cpp/utility/to_chars the fourth argument seems to be an
std::chars_format which doesn't seem to be of integral type.

Also while going through this https://en.cppreference.com/w/cpp/language/sizeof I found
this
1
2
3
4
struct Bit { unsigned bit: 1; };//is there an unsigned bit in c++?
sizeof(Bit) //6) size of Bit class: 4 bytes(simply 32 bits) : this seems to be a lot of memory wasted just to represent
//a single bit?


Please recomend me a good c++ 20 compiler and good books for both c++ 17 and 20, I'd really appreciate it.

Thanks in advance.
> does this view still contain the original message or the corrupted message

The string view would refer to the characters in the string;
"a typical implementation holds only two members: a pointer to constant CharT and a size"
https://en.cppreference.com/w/cpp/string/basic_string_view
The view would therefore refer to the characters in the corrupted string, but the size would be that of the original string. It is a bad situation to get into.


> the fourth argument seems to be an std::chars_format which doesn't seem to be of integral type.

The fourth std::chars_format parameter is used only by the overloads for floating point types, it specifies the floating-point format that should be used.

We are using integer values, the overload is overload (1), the fourth parameter is the integer base to be used. We pass 16 because we want a hexadecimal representation.


> a good c++ 20 compiler

On windows, go for the microsoft compiler (Visual Studio Community Edition).
On Unix-like systems, either the GNU compiler (gcc/g++) or the LLVM compiler (clang/clang++).


> good books for both c++ 17 and 20

Two books covering C++17:

Overview: Stroustrup's 'A Tour of C++ (2nd Edition)'
https://www.amazon.com/Tour-2nd-Depth-Bjarne-Stroustrup/dp/0134997832

More detailed: Josuttis's 'C++17 - The Complete Guide: First Edition'
https://www.amazon.com/C-17-Complete-Guide-First/dp/396730017X
1
2
3
struct Bit { unsigned bit: 1; };//is there an unsigned bit in c++?
sizeof(Bit) //6) size of Bit class: 4 bytes(simply 32 bits) : this seems to be a lot of memory wasted just to represent
//a single bit? 


The first form is using what's called Bit Field. Forget the name for the moment. A bit field defines a struct data member with explicit size, in bits and it's type. So:

1
2
3
struct S {
    int b : 3;
};


b is a 3 bit variable of type int. It can hold values -4 to 3.

1
2
3
struct S {
    unsigned b : 2;
};


b is a 2 bit variable of type unsigned int. It can hold values 0 to 3.

So:

1
2
3
struct Bit { 
    unsigned bit: 1; 
};


where bit is a 1 bit variable of type unsigned int. It can hold values 0 and 1.

Consider, however:

1
2
3
struct Bit { 
    signed bit: 1; 
};


where bit is signed. In this case it can hold values of -1 and 0.

sizeof(Bit) gives the size of the memory used to hold the struct. As the type of a bit field can only be an integral or enumeration type, the minimum size is of the type used. If the type of bit had been say unsigned char rather than unsigned int, then the sizeof(Bit) would have been 1.

Bit fields are usually used to separate out bits that have specific meaning. eg

1
2
3
4
5
6
struct Data {
    unsigned char dat1 : 3;
    unsigned char dat2 : 1;
    unsigned char dat3 : 2;
    unsigned char dat4 : 2;
};


sizeof(Data) is 1 as 8 bits are used, each an unsigned char which are packed together within 8 bits. The issue with bit fields is endiness!

See https://en.cppreference.com/w/cpp/language/bit_field
> sizeof(Data) is 1 as 8 bits are used, each an unsigned char which are packed together within 8 bits.

sizeof a class object containing bit-fields is implementation-defined.

IS:
Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined.
http://eel.is/c++draft/class.bit#1


The only guarantee is 'Bit-fields are packed into some addressable allocation unit.'
For books on C++17/20:

C++20 - the Complete Guide by Nicolai Josuttis
https://leanpub.com/cpp20

C++20 by Rainer Grimm
https://leanpub.com/c20

C++17 In detail Bartłomiej Filipek
https://leanpub.com/cpp17indetail

Mastering the C++17 STL
https://www.amazon.co.uk/Mastering-17-STL-standard-components/dp/178712682X/ref=sr_1_6?dchild=1&keywords=c%2B%2B17&qid=1625934409&s=books&sr=1-6

There's also several 'intro' books that cover c++17/C++20. Of these, I like

Beginning C++20: From Novice to Professional by Ivor Horton
https://www.amazon.co.uk/Beginning-C-20-Novice-Professional/dp/1484258835/ref=sr_1_4?dchild=1&keywords=c%2B%2B20&qid=1625934452&s=books&sr=1-4

Also useful/recommended is:

Professional C++ by Marc Gregoire
https://www.amazon.co.uk/Professional-C-Marc-Gregoire/dp/1119695406/ref=sr_1_4?crid=2J002VYUTZ11M&dchild=1&keywords=c%2B%2B+professional&qid=1625934544&sprefix=c%2B%2B+prof%2Caps%2C168&sr=8-4

Make sure you get the latest (5th) edition.
Last edited on
Thank you very much, haven't seen another forum where people are so helpful.

@JlBorges
It is a bad situation to get into. I agree but hope the compiler would raise an exception when the read goes out of bound. I can't test the code because I still lack any compiler with <string_view> header , I'll download visua studio && Gcc.

the overload is overload (1) I don't know how I missed it.

@SeePlus The first form is using what's called Bit Field. Forget the name for the moment. A bit field defines a struct data member with explicit size, in bits and it's type.
Yea that explanation is very clear couldn't have asked for more.

Thanks for those book recommendations, I'm sure they'll get me going given my c++ knowledge is super rusty.



Also one more question:
Is there a way I would get/determine the time slice allocated for a single thread by the scheduler in c++, If I can get that time I could use it to detect whether a debugger is attached to a process because of the pauses, I'm porting some other function and that would be handy.



Thank you.
Last edited on
> I agree but hope the compiler would raise an exception when the read goes out of bound.

Keep it simple; copy the characters in the message into another string.
1
2
3
4
5
std::string Mssg = acquire_message();//gets a message from somewhere
// std::string_view mssg_view{Mssg.begin(),Mssg.end()}; //valid view of the message

const std::string Mssg_copy = Mssg; //make a copy of the message
std::string_view mssg_view{Mssg_copy.begin(),Mssg_copy.end()}; //valid view of the copy of the message 



> detect whether a debugger is attached to a process

Since you are using windows:

Is a debugger attached to the current process? IsDebuggerPresent()
https://docs.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-isdebuggerpresent

Is a debugger attached to another process? CheckRemoteDebuggerPresent()
https://docs.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-checkremotedebuggerpresent

To get thread times: GetThreadTimes()
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreadtimes
1
2
template < typename T >
typename std::enable_if< std::is_integral<T>::value, std::string_view >::type hex_str_view( T value )


Rather than using a template, with C++20 you can use concepts - which can simply things a bit.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <string>
#include <iterator>
#include <type_traits>
#include <concepts>

std::string toHexStr(std::integral auto w) {
	static const char* const digits {"0123456789ABCDEF"};

	std::string rc(sizeof(w) << 1, '0');
	auto itr {rc.rbegin()};

	for (auto wu {std::make_unsigned_t<decltype(w)>(w)}; wu; wu >>= 4)
		*itr++ = digits[wu & 0x0f];

	return itr == rc.rbegin() ? "0" : std::string(itr.base(), rc.end());
}


Here L7 is using concepts with the auto for the function param type. That type must be integral as the proceeding concept (std::integral) specifies.

Using concepts like this can also be easily applied to the other hex conversion codes.
@JLBorges thanks for the information I'll look those up and if I get any question I'll ask but I wanted to stay away from well developed apis as most debuggers can patch them to prevent the process it self from detecting them, I'll see how close I can get.


@Seeplus This seems great but I don't yet know about concepts but for now I got a few books and I'm going through them rn.

static const char* const digits {"0123456789ABCDEF"}; why does this have two consts?

Here L7 is using concepts with the auto for the function param type.
What is L&?


> Rather than using a template, with C++20 you can use concepts - which can simply things a bit.

Concepts - particularly concepts defined by the library - can simplify things. But even if it does not look like a
pre-C++20 template, it still is very much a function template (a constrained function template).


> static const char* const why does this have two consts

Two consts to specify constant pointer to constant char.

We could also write: static const char digits[] = "0123456789ABCDEF" ; // array of const char
The array decays to a pointer on demand.
Thank you, that explanation is very clear.
Topic archived. No new replies allowed.
Pages: 12