Sets are serialized by first ordering the elements, and then packing them as a sequence which is also how lists are represented when PACK is called. This means that these two expressions evaluate to the same, since they are first sorted, and then serialized.
ligo interpret -s pascaligo 'Bytes.pack(set [ 1; 2; 3; 4 ])'
ligo interpret -s pascaligo 'Bytes.pack(...
Here is a break down:
05: all michelson values are tagged with the prefix 0x05 (ref).
07: the first tag denotes the micheline constructor. Pair 1 2 is a primitive application with 2 arguments and no annotation. The corresponding tag is 0x07.
07: the next tag denotes the michelson primitive. It so happens that the corresponding tag is also 0x07.
Strings are serialized as follows:
01 to indicate type string
Four bytes (eight hex chars) to indicate length of string: 0000000c=0x0c=12 in your case
The string represented by its ASCII values: 48656c6c6f20576f726c6421 in your case
The 05 in the beginning is a prefix which is only used by the PACK Michelson instruction which the Bytes.pack function in ...
The 05 prefix indicates that this serialization comes from the PACK assembly instruction, and the next byte 00 in case of integers (nat, int, and tez) indicates that the type is integer. So the numbers are represented by the bytes
01 for 1n
80897a for 1000000n (1 million)
Reading each byte from left to right, the 1st indicates whether more bytes are coming....