BIN files are just "BINary" data. The file just contains a byte stream of the data. Since there's no provision in a BIN file for any control data, you need to specify a starting address when loading a BIN.
Note that COM files are identical to BIN files, but they always start at 0100h. So if you assemble your BIN files to 0100h, your programs can be run from CP/M.
On the other hand, Hex files have the address built in to the file format, and every line in the file allows you to set a new address. Hex files are plain ASCII files, with the data encoded in hex format.
So a hex file could, for example, load code at 100h-400h, then load a bunch of data at 2000h.
Here's a line from a hex file:
:
10010000214601360121470136007EFE09D2190140Hex file lines always start with a :
10 is the record size (16 bytes)
0100 is the address of this line of data.
00 is the record type (00=data, 01=end of file)
the next 32 characters are the data in hex (16 bytes worth)
the 40 at the end is a checksum of all the bytes on the line. (Add the values and get the two's complement.)
The Wikipedia page is actually pretty good, and I've written both hex encoders and loaders from this description:
https://en.wikipedia.org/wiki/Intel_HEX