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;
GeeRodreezy
  • 1
  • 1
  • 3
  • You need to specify the word size for byte swapping, e.g. 2 bytes, 4 bytes or some other word size. – Paul R Sep 14 '15 at 21:08
  • It's every 2 bytes I believe... – GeeRodreezy Sep 14 '15 at 21:09
  • Surely there are plenty of extant resources that can teach you how to swap bytes within an array? – Lightness Races in Orbit Sep 14 '15 at 21:09
  • 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 internship – GeeRodreezy Sep 14 '15 at 21:11
  • 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. – Paul R Sep 14 '15 at 21:12
  • @PaulR you are correct on the file type. Mind pointing me in the right direction? – GeeRodreezy Sep 14 '15 at 21:13
  • 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. http://stackoverflow.com/questions/7895046/library-for-manipulating-s-record-and-intel-hex-16-files and http://stackoverflow.com/questions/7569253/how-can-i-fill-an-s-record-with-two-byte-values-starting-on-even-address-boundar – Paul R Sep 14 '15 at 21:14
  • Thanks, I'll take a look :) – GeeRodreezy Sep 14 '15 at 21:18
  • The [Wikipedia page for S record file format](https://en.wikipedia.org/wiki/SREC_%28file_format%29) also has some useful info and links to tools etc. – Paul R Sep 14 '15 at 21:20
  • Search C++ endian in the StackOverflow search box above. This question has been asked and answered many times. – rodamn Sep 14 '15 at 22:45
  • possible duplicate of [How do I convert between big-endian and little-endian values in C++?](http://stackoverflow.com/questions/105252/how-do-i-convert-between-big-endian-and-little-endian-values-in-c) – rodamn Sep 14 '15 at 22:45
  • @rodamn it's a bit different (refer to EDIT) – GeeRodreezy Sep 14 '15 at 23:35

2 Answers2

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.

Kirkova
  • 319
  • 1
  • 9
  • But that would only be for a constant int, right? I have to read and swap for each line in the record. – GeeRodreezy Sep 14 '15 at 21:31
  • 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. – Kirkova Sep 14 '15 at 21:38
  • 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? – GeeRodreezy Sep 14 '15 at 22:03
  • That's not doing an endian swap, that's swapping the lower and upper 16 bits. – mattnewport Sep 14 '15 at 22:49
  • @mattnewport 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. – GeeRodreezy Sep 14 '15 at 23:23
  • @mattnewport 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. – Kirkova Sep 15 '15 at 17:29
  • @Kirkova 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. – mattnewport Sep 15 '15 at 17:45
  • At this point I'll try both ways and see what happens lol, nibble and byte. Thanks guys – GeeRodreezy Sep 15 '15 at 17:54
  • @mattnewport nibble swap didn't work and when i try to "byte swap" mentioned above I get an "OUT OF MEMORY LOCATION ERROR" – GeeRodreezy Sep 15 '15 at 21:41
  • 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. – Kirkova Sep 15 '15 at 21:49
  • @Kirkova 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;` – GeeRodreezy Sep 15 '15 at 22:56
  • Looks like I have to somehow change the STOI to a short – GeeRodreezy Sep 15 '15 at 23:14
  • @GeeRodreezy 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! – Kirkova Sep 17 '15 at 17:36
  • @Kirkova 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.. – GeeRodreezy Sep 17 '15 at 18:38
  • @GeeRodreezy 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. – Kirkova Sep 17 '15 at 18:59
  • @Kirkova 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 lol – GeeRodreezy Sep 17 '15 at 20:23
  • 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. – Kirkova Sep 17 '15 at 22:35
  • @Kirkova 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?? – GeeRodreezy Sep 18 '15 at 23:04
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.