Byte Swap with an array?
Asked Answered
B

2

0

First of all, forgive my extremely amateur coding knowledge. I am intern at a company and have been assigned to create a code in C++ that swaps bytes in order to get the correct checksum value.

I am reading a list that resembles something like: S315FFF200207F7FFFFF42A000000000001B000000647C S315FFF2003041A00000FF7FFFFF0000001B00000064ED S315FFF2004042480000FF7FFFFF0000001E000000464F

I have made the program convert this string to hex and then int so that it can be read correctly. I am not reading the first 12 chars or last 2 chars of each line.

My question is how do I make the converted int do a byte swap (little endian to big endian) so that it is readable to the computer? Again I'm sorry if this is a terrible explanation.

EDIT: I need to essentially take each byte (4 letters) and flip them. i.e: 64C7 flipped to C764, etc etc etc. How would I do this and put it into a new array? Each line is a string right now...

EDIT2: This is part of my code as of now...

    int j = 12;

                    for (i = 0; i < hexLength2 - 5; i++){

                        string convert1 = ODL.substr(j, 4);

                        short input_int = stoi(convert1);
                        short lowBit = 0x00FF & input_int;
                        short hiBit = 0xFF00 & input_int;

                        short byteSwap = (lowBit << 8) | (hiBit >> 8);

I think I may need to convert my STOI to a short in some way..

EDIT3: Using the answer code below I get the following... HEX: 8D --> stored to memory (myMem = unsigned short) as 141 (decimal) -->when byte swapped: -29440 Whats wrong here??

            for (i = 0; i < hexLength2 - 5; i++){

                        string convert1 = ODL.substr(j, 2);
                        stringstream str1;
                        str1 << convert1;
                        str1 >> hex >> myMem[k];

                        short input_int = myMem[k];                     //byte swap 
                        short lowBit = 0x00FF & input_int;              
                        short hiBit = 0xFF00 & input_int;               
                        short byteSwap = (lowBit << 8) | (hiBit >> 8);  
                        cout << input_int << endl << "BYTE SWAP: " <<byteSwap <<"Byte Swap End" << endl;    
                        k++;
                        j += 2;
Bioastronautics answered 14/9, 2015 at 21:4 Comment(12)
You need to specify the word size for byte swapping, e.g. 2 bytes, 4 bytes or some other word size.Kilimanjaro
It's every 2 bytes I believe...Bioastronautics
Surely there are plenty of extant resources that can teach you how to swap bytes within an array?Optimal
I've found the _byteswap_ushort function but have no clue how to correctly use it. I'm an electrical engineering major doing the job of a software engineer lol i've only taken 1 c++ class prior to this internshipBioastronautics
Also this looks like a standard Motorola S record hex file - there should be plenty of code examples out there for reading writing between this format and binary.Kilimanjaro
@PaulR you are correct on the file type. Mind pointing me in the right direction?Bioastronautics
I would start with a web search for "Motorola S record hex source code" or something like that. There are even useful questions and answers right here on SO, e.g. #7895546 and #7569753Kilimanjaro
Thanks, I'll take a look :)Bioastronautics
The Wikipedia page for S record file format also has some useful info and links to tools etc.Kilimanjaro
Search C++ endian in the StackOverflow search box above. This question has been asked and answered many times.Dolan
possible duplicate of How do I convert between big-endian and little-endian values in C++?Dolan
@Dolan it's a bit different (refer to EDIT)Bioastronautics
S
1

You can always do it bitwise too. (Assuming 16-bit word) For example, if you're byte swapping an int:

short input_int = 123; // each of the ints that you have

short input_lower_half = 0x00FF & input_int;
short input_upper_half = 0xFF00 & input_int;

// size of short is 16-bits, so shift the bits halfway in each direction that they were originally
 short byte_swapped_int = (input_lower_half << 8) | (input_upper_half >> 8)

EDIT: My exact attempt at using your code

unsigned short myMem[20];
int k = 0;
string ODL = "S315FFF2000000008DC7000036B400003030303030319A";

int j = 12;
for(int i = 0; i < (ODL.length()-12)/4; i++) { // not exactly sure what your loop condition was

    string convert1 = ODL.substr(j, 4);
    cout << "substring is: " << convert1 << endl;
    stringstream str1;
    str1 << convert1;
    str1 >> hex >> myMem[k];

    short input_int = myMem[k];                     //byte swap
    unsigned short lowBit = 0x00FF & input_int; // changed this to unsigned
    unsigned short hiBit = 0xFF00 & input_int; // changed this to unsigned
    short byteSwap = (lowBit << 8) | (hiBit >> 8);
    cout << hex << input_int << " BYTE SWAPed as: " << byteSwap <<", Byte Swap End" << endl;
    k++;
    j += 4;
}

it only matters to change the loBit and hiBit to be unsigned since those are the temporary values we're using.

Slam answered 14/9, 2015 at 21:30 Comment(18)
But that would only be for a constant int, right? I have to read and swap for each line in the record.Bioastronautics
This does not only apply to const ints , you could use this for non-const ints as well. All this would do is read in an int, not caring about whether it is const. And yes, this would only be for one int, but you said that you took a string -> hex -> int, so this if you used this approach, you would loop through all the ints, doing this for all of them.Slam
When i converted I stored them in memory (myMem[j]), so would that be my input_int or should I create another variable that converts the original record string into an int and use that?Bioastronautics
That's not doing an endian swap, that's swapping the lower and upper 16 bits.Glycerinate
@Glycerinate you're correct, it's not what I need to do lol I need to essentially take each word (2 letters) and flip them. i.e: C7 flipped to 7C, etc etc etc.Bioastronautics
@Glycerinate Wow, I wasn't thinking, it should be corrected now as well with what OP commented earlier about the words being two bytes. Coincidentally, it looks very similar, but since the words are only two bytes, the 8-bit shift is all you need to do.Slam
@Slam it's still a little unclear what the OP is asking. Converting 0xC7 to 0x7C is not a byte swap either, it's a nibble swap. I don't think that's what he actually wants to do though, I assume he wants what your edited code shows, e.g. 0x647C to 0x7C64.Glycerinate
At this point I'll try both ways and see what happens lol, nibble and byte. Thanks guysBioastronautics
@Glycerinate nibble swap didn't work and when i try to "byte swap" mentioned above I get an "OUT OF MEMORY LOCATION ERROR"Bioastronautics
I just double-checked my example on my machine to make sure the output is correct to swap the two bytes and it worked. Be sure that the input word you're using is a short like I'm using. This will ensure 16 bits. I'm not sure why you would get that error. It might depend on exactly how you are looping through and what data types you are using.Slam
@Slam Would I have to read 4 digits at a time? Right now I am only reading 2 at a time.. for (i = 0; i < hexLength2 - 5; i++){ string convert1 = ODL.substr(j, 2); short input_int = stoi(convert1); short lowBit = 0x00FF & input_int; short hiBit = 0xFF00 & input_int; short byteSwap = (lowBit << 8) | (hiBit >> 8); k++; j += 2;Bioastronautics
Looks like I have to somehow change the STOI to a shortBioastronautics
@Bioastronautics Sorry, been busy. It's half right, half wrong. -29440 is the expected output if you only read 2 characters in. -29440 = (hex 8D00). It's negative because of numbers being read as 2's complement. If the highest bit is 1, it is negative (a little more than that, but whatever). So, with 8D being the input, you got the correct output. However, you were correct, you need to be reading 4 digits in at a time. each hex digits is only 4 bits, so right now you're only reading in 8 bits = 1 byte. Read in all 4 characters for 16 bits, and hopefully that will be it!Slam
@Slam So I changed convert1 to (j,4).. If i am reading a line such as: S315FFF2000000008DC7000036B400003030303030319A It SHOULD be reading the four 0's prior to the first 8 and swap those, then swap 8DC7...BUT for some reason I'm reading in 008D and swapping that..Bioastronautics
@Bioastronautics I'm assuming you still have j = 12 like in EDIT2. If so, I'm really not sure. Does it skip the 0000 entirely? Also, don't forget you need to do j+=4 now. If it has the 0000 and then does 008D, that makes sense because it would have only shifted by 2 characters. If not this, debug your variables as the loop starts either with a debugger or just with cout statements.Slam
@Slam Well now that I try that, I am getting 8DC7 swapped to -115 BUT as I am trying to calculate a CRC out of the whole record I am getting an incorrect result. The code is defeating me lolBioastronautics
I just tried going through this myself and did find one mistake with what I gave you originally. It affected the what some of the shifted values were. Using an unsigned short instead of short gave me an incorrect value for 8DC7, I'm updating my answer with exactly what I tried.Slam
@Slam UPDATE!!!! I am looking at line: S30DFFF200000000E5CC075BCD150C using only data line: 0000E5CC075BCD15 When the byte swap happens it load E5 into hiByte and CC into low byte BUT when i do the swap above in your answer I get FFE5 Why does it get rid of my CC??Bioastronautics
J
0

If you're asking what I think you're asking-

First, you need to make sure you know what size your integers are. 32 bits is nice and standard, but check and make sure.

Second, cast your integer array as a char array. Now you can access and manipulate the array one byte at a time.

Third- just reverse the order of every four bytes (after your first 12 char offset). Swap the first and fourth and the second and third.

Jeepers answered 14/9, 2015 at 21:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.