0

This program takes the command line argument and fill write_key array

#include <stdio.h>
#include <stdlib.h>

 int main(int argc, char **argv)
 {
   int i,j;
   unsigned char write_key[16];

   for(j=0;j<4;j++){
     for(i=0;i<4;i++){
       write_key[j*4 + i] = (strtol(argv[1+j],NULL,16)>>(8*(4-1-i))) & 0xff;
     }
   }

   for(i=0;i<16;i++){
     printf("write_key[%d] :: 0x%x   \n", i, writekey[i]);
   }
  printf("\n");
}

I launch the program with

./app 0xffffffff 0xffffffff 0xffffffff 0xffffffff 

For following input output on my linux pc is

write_key[0] :: 0xff   
write_key[1] :: 0xff   
write_key[2] :: 0xff   
write_key[3] :: 0xff   
write_key[4] :: 0xff   
write_key[5] :: 0xff   
write_key[6] :: 0xff   
write_key[7] :: 0xff   
write_key[8] :: 0xff   
write_key[9] :: 0xff   
write_key[10] :: 0xff   
write_key[11] :: 0xff   
write_key[12] :: 0xff   
write_key[13] :: 0xff   
write_key[14] :: 0xff   
write_key[15] :: 0xff

Which is as expected. but when i cross compiled this program for Mips based embedded board and run it there my output is.

write_key[0] :: 0x7f   
write_key[1] :: 0xff   
write_key[2] :: 0xff   
write_key[3] :: 0xff   
write_key[4] :: 0x7f   
write_key[5] :: 0xff   
write_key[6] :: 0xff   
write_key[7] :: 0xff   
write_key[8] :: 0x7f   
write_key[9] :: 0xff   
write_key[10] :: 0xff   
write_key[11] :: 0xff   
write_key[12] :: 0x7f   
write_key[13] :: 0xff   
write_key[14] :: 0xff   
write_key[15] :: 0xff 

Why there is a difference in output for different architecture ?

LPs
  • 16,045
  • 8
  • 30
  • 61
saurabh agarwal
  • 2,124
  • 4
  • 24
  • 46
  • 1
    Have you done any debugging? For example, what does `strtol("ffffffff", NULL, 16)` return on the two platforms? – melpomene Oct 18 '16 at 08:53

2 Answers2

3

strtol returns a long, possibly a 32 bit integer, signed. It ranges from -1 (0xFFFFFFFF) to 0x7FFFFFFF.

The shifting may behave differently on negative numbers depending on the compiler as stated here and here (Right-shifting negative numbers invoke implementation-defined behavior in C)

That's probably why you have the problem: EDIT: I was right about the probably :), After melponeme comment, I just tested the result of strtol("0xffffffff) on a 32-bit compiler and it returns 0x7FFFFFFF, so the problem is not the shifting.

What I'm sure will solve your problem, is that switching to strtoul to return unsigned long will do the trick: it will return an unsigned long (first problem solved) and it will be sure that the shifting will work as you want.

As a final note, I would recommend that you use a 32-bit compiler on your Linux machine (even if the machine is 64-bit) so you're closer to your target architecture and you'll detect problems like that earlier.

Community
  • 1
  • 1
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
3

strtol returns a long int. If long int is 32 bits wide on on your platform, then it can't represent 0xffffffff (which is about 4 billion).

man strtol:

The strtol() function returns the result of the conversion, unless the value would underflow or overflow. If an underflow occurs, strtol() returns LONG_MIN. If an overflow occurs, strtol() returns LONG_MAX.

So it returns LONG_MAX, which in 32 bits is 0x7fffffff (or about 2 billion), because that's the biggest positive 32-bit number.

Presumably your Linux PC uses 64-bit long ints so this problem doesn't occur there.

To fix this problem, change the code to use strtoul, because 0xffffffff fits just fine into an unsigned long int.

melpomene
  • 84,125
  • 8
  • 85
  • 148