-1

I'm trying to read a binary file two bytes at a time and display the result. I came up with the following:

int main() {
    char opcode[2];
    FILE *fp;

    fp = fopen("games/PONG", "rb");

    while( fread(opcode, 1, 2, fp) != 0 ) {
        printf(" %02X%02X\n", opcode[0], opcode[1]);
    }
}

It sort of works:

$ ./c8disas
 6A02
 6B0C
 6C3F
 6D0C
 FFFFFFA2FFFFFFEA
 FFFFFFDAFFFFFFB6
 FFFFFFDCFFFFFFD6
 6E00
 ...

Some of the lines in the output contain additional FF bytes, and I don't understand where they come from.

For reference, this is the binary I'm reading:

$ hexdump -C games/PONG
00000000  6a 02 6b 0c 6c 3f 6d 0c  a2 ea da b6 dc d6 6e 00  |j.k.l?m.......n.|
00000010  22 d4 66 03 68 02 60 60  f0 15 f0 07 30 00 12 1a  |".f.h.``....0...|
00000020  c7 17 77 08 69 ff a2 f0  d6 71 a2 ea da b6 dc d6  |..w.i....q......|
00000030  60 01 e0 a1 7b fe 60 04  e0 a1 7b 02 60 1f 8b 02  |`...{.`...{.`...|
00000040  da b6 60 0c e0 a1 7d fe  60 0d e0 a1 7d 02 60 1f  |..`...}.`...}.`.|
...
Juicy
  • 11,840
  • 35
  • 123
  • 212
  • 5
    Try reading into an `unsigned char` instead. Values greater than or equal to `0x80` are sign-extended with `char` here. – Daniel Kamil Kozar Sep 23 '15 at 18:08
  • 1
    possible duplicate of [Printing hexadecimal characters in C](http://stackoverflow.com/questions/8060170/printing-hexadecimal-characters-in-c) – phuclv Sep 23 '15 at 18:25
  • there were already so many duplicates here – phuclv Sep 23 '15 at 18:25
  • Every integer argument smaller than 4 bytes which is passed to function `printf` is expanded to 4 bytes. When a `signed char` argument is expanded to 4 bytes, each one of the 3 added bytes is 0xFF if the value is negative, and 0x00 if the value is non-negative. You can use `%.2X` if you want `printf` to avoid printing those 3 bytes. Alternatively, you can declare the argument as `unsigned char`. – barak manos Sep 23 '15 at 18:26

2 Answers2

3

char is normally a signed integer by default. So the high order bits are sign extended when it's widened to an int before being passed to printf(). Use unsigned char instead.

You can also AND (&) with 0xff to strip off other bits but you really should be using an unsigned value here.

Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466
2

The FFs come from the negative bit (I know it %X is supposed to be unsigned). Try:

printf(" %02X%02X\n", 0xFF & opcode[0], 0xFF & opcode[1]);
MtCS
  • 305
  • 1
  • 9