Why if i check with the xxd an image eg. small.bmp the bfType is 0x424d and when you run copy in GDB the value of bf.bfType is 19778 and the program "copy" in line 55 check with 0x4d42. Is it reading it reverse order.
1 Answer
bfType is an unsigned 16 bit integer (ie, 2 bytes long, aka a WORD).
What you are seeing is the fact that xxd
displays byte by byte, but gdb
displays the word.
So why does it matter?
Intel processors use what is called "little endian" to store bytes in memory. That means that the least significant byte is stored in the first memory address in the word.
So gdb is showing you the decimal value 19778 (even though, in reality, bfType is 2 chars (B and M) and not an integer). If you convert to hex (which I think you've done) it is 0x4D42
. That is the value that copy.c
is testing against.
The value 0x4D42
in a little endian system will be stored in byte order as 424D
(how xxd
is showing you).
One way to think about little endian is to think of a decimal number.
If you write 123
, the least significant number is 3
and it is at the end, so our number system of writing is "big endian", the opposite of what our computers use.
If our number system was "little endian", then we would write "one hundred twenty three" as 321.
The entry for Endianness on Wikipedia can explain it much more detail.
But let's look at an example from the class. If you take small.bmp
that is given and run xxd
to see the individual bytes, you'll get this. I've added spaces between some bytes to make it clearer:
424d 5a000000 00000000 36000000 28000000 03000000
fdffffff 0100 1800 00000000 24000000 120b0000 120b0000
00000000 00000000
00ff00 00ff00 00ff00 00 00 00
00ff00 ffffff 00ff00 00 00 00
00ff00 00ff00 00ff00 00 00 00
So you've got a printout of the bytes of the file. What do they mean? This is where you use the bmp.h
file to get the structure. Recall from the typedef's that a WORD is a unsigned 16 bit (ie, 2 byte) integer, a DWORD is an unsigned 32 bit (4 byte) integer and a LONG is a signed 32 bit (4 byte) integer. So we can then just count the bytes as we go along and assign them to their values.
Remember that the bytes are stored in little-endian fashion, with least significant byte stored first, so to calculate the decimal value, we need to think of them in the opposite order.
BITMAPFILEHEADER: Bytes: Hex = Decimal value:
WORD bfType; 42 4d 0x4d42 = 19778
DWORD bfSize; 5a 00 00 00 0x0000005a = 90
WORD bfReserved1; 00 00 0x0000 = 0
WORD bfReserved2; 00 00 0x0000 = 0
DWORD bfOffBits; 36 00 00 00 0x00000036 = 54
BITMAPINFOHEADER:
DWORD biSize; 28 00 00 00 0x00000028 = 40
LONG biWidth; 03 00 00 00 0x00000003 = 3
LONG biHeight; fd ff ff ff 0xfffffffd = -3
WORD biPlanes; 01 00 0x0001 = 1
WORD biBitCount; 18 00 0x0018 = 24
DWORD biCompression; 00 00 00 00 0x00000000 = 0
DWORD biSizeImage; 24 00 00 00 0x00000024 = 36
LONG biXPelsPerMeter; 12 0b 00 00 0x00000b12 = 2834
LONG biYPelsPerMeter; 12 0b 00 00 0x00000b12 = 2834
DWORD biClrUsed; 00 00 00 00 0x00000000 = 0
DWORD biClrImportant; 00 00 00 00 0x00000000 = 0
RGBTRIPLE:
BYTE rgbtBlue; 00 0x00 = 0
BYTE rgbtGreen; ff 0xff = 255
BYTE rgbtRed; 00 etc... 0x00 = 0
Those values in the last column should match what you see if you use the peek
program to look at the headers of small.bmp
.
Hope that helps, Brenda.
-
1Wow, you blow up my mind. I haven't heard before about endians. The thing now is that the rest of the vars seams to be read with GDB right,. The same with xxd bfType is BM and the rest is reverse written. So i guess that the convention of starting with BM refers to the disc, and i will find it always reverse in GDB?– dizcolaCommented Aug 2, 2014 at 19:20
-
-
Thanks for the detailed answer. It was also the exact answer to my question.– BcKCommented Mar 29, 2017 at 22:22
-
Thanks for the big and little endian explanation! Now I get it!– legalbotCommented Jul 23, 2019 at 21:56
peek
instead ofxxd
:)