Here is another solution that uses shifts but I believe is "cleaner" (though not as clean as David's suggestion):
result := MSB;
result := (result shl 8) or b2; { could use "shl sizeof(b2)" instead of 8 }
result := (result shl 8) or b3;
etc
result := (result shl 8) or b8;
this solution avoids all the "magic" shifting values and it is probably easier to understand. Also, if MSB..b8 (or b1..b8) were an array of bytes, the above code could easily be converted into a single line loop.
To answer your question as to why the compiler does not accept the value 40 and above, the reason is most likely due to this quote from Volume 2B of the Intel Instruction Set Reference for the SHLD instruction:
In non-64-bit modes and default 64-bit
mode; only bits 0 through 4 of the
count are used. This masks the count
to a value between 0 and 31. If a
count is greater than the operand
size, the result is undefined.
The equivalent condition on the SHL instruction is not quite as stringent:
The 8086 does not mask the shift
count. However, all other IA-32
processors (starting with the Intel
286 processor) do mask the shift count
to 5 bits, resulting in a maximum
count of 31. This masking is done in
all operating modes (including the
virtual-8086 mode) to reduce the
maximum execution time of the
instructions.
In either case, a value greater than 31 is either useless (when using SHL) or undefined (when using SHLD). The compiler obviously knows this and, it is preventing you from writing code that is potentially erroneous (in 64 bit mode.)
if you, indeed are doing this operation 50 BILLION times, then you may want to consider doing it in inline assembly, which would be quite simple:
asm
xor eax, eax
or eax, MSB { or b1 depending on how you named the MSB }
shl eax, 8
or eax, b2
shl eax, 8
or eax, b3
shl eax, 8
or eax, b4
mov High32bit, eax
end;
and repeat the above operation for the low 32 bit dword and b5 thru b8. I didn't suggest using SHLD because I don't believe Delphi supports the 64 bit registers nor 64bit instructions (I could be wrong, I've never tried it.)
Note: I've heard rumors that the 64bit version of Delphi will not support inline assembly. This may or may not be the case but, I would stay away from inline assembly unless it is truly absolutely necessary.
Hope that helps,
John.
PS: there is another reason why David Heffernan's solution is the best one. In the solution I presented, every instruction depends on the previous instruction (that is, eax must be shifted by 8 before the next "or" instruction can be executed). David's solution sets individual bytes, as such, each assignment is independent of the previous assignment, this will allow the processor to potentially carry out multiple assignments in parallel. In this era of multi-core processors this has the potential of being quite a bit faster than the assembly code I gave as an example.