The logic behind this is that the mask is bitwise or'ed with the address:
192.168.1.1 =11000000.10101000.00000001.00000001
255.255.255.0 = 11111111.11111111.11111111.00000000
11000000.10101000.00000001.00000001 | 11111111.11111111.11111111.00000000 = 11111111.11111111.11111111.00000001
The first 3 bytes all become 255.
Johannes, I have been meaning to comment on this. The subnet mask and destination IP are logically ANDed together not OR.
The Boolean's of comparison:
AND (conjunction)- True if both bits are true (this and that)
OR - (disjunction) - True if either or both bits are true
XOR - (exclusionary disjunction) True if one or the other is true (this or that but not both)
I know that Keith said TMI and I am sure it seems that way but microprocessors are not floating point devices. They are switches. Stateful machines for a lack of a better word. These groups of bits are called registers. Back before silicon was cheap a 16 bit register was a very valuable resource. The microprocessor machine language only speaks in these boolean primitives. Returning a single bit based on the comparison of two registers.
So when Mr. Metcalfe and his brilliant team designed IP addressing they used 4 octets. Each was loaded from a stack and pop'd and pushed through the registers. Pushing 4 - 16 bit integers through the registers was very quick. This allowed super efficient address decoding in the driver stack.
Hexadecimal notation is just a simple way to represent these base 16 numbers (how people with 16 fingers count). 16 bits was a very common register size for the 8 bit microprocessors of the day when Ethernet was invented.
The technology lasted a long time and we are only slowly moving to IPV6's vastly larger address space.