bob wrote:With the deranged reasoning here, if one does a BSF instruction and the source is all zero bits, the destination register is undefined. Should the program crash? Because you can always use a "jz" to determine that there were no one bits set and eax has no useful value in it (actually, it is unchanged from its contents prior to executing the bsf).
There's no C language construct that maps to BSF, but just suppose for a moment there was and that the language spec said it was "undefined behavior" to use the value from the destination register after a BSF with all zero source bits. All kinds of weird stuff could happen if the programmer didn't respect that undefinedness.
The compiler might notice that you are assigning the destination register to a variable. If you happened to pass in all zero bits, then the contents of the register are undefined, and so is the variable. So in a branch that uses that variable, it might assume that your source for the BSF was non-zero. It might then delete an if-statement comparing that source with zero.
Another example: the compiler might be able to prove that if reached via a certain control path, the BSF was executed with all zero bits as the input. It might hoist the BSF and subsequent instructions onto each path, and then delete the BSF that produces the undefined result, and any instructions on that path using the result (it might do this because of a partial redundancy elimination pass, for example).
Similar odd-sounding narratives exist for things like shifting into or out of the sign bit in signed ints, dividing INT_MIN by -1, dividing by zero, and so on. So its best to just never do them. Even if it happens to work _today_, on some compilers and some library versions, that is probably a temporary state of affairs. Now that they have a taste for the optimization benefits, it will take a bloody revolution to convince compiler vendors to stop taking advantage of the freedoms that the language has always reserved to them.
You can't reason your way up from how the low-level machine works to how a C construct is going to work, if that C construct happens to invoke "undefined behavior" according to the C language standard. Any reasoning of that sort is fallacious and dangerous. The only way you can know your program is correct is to (1) test it under the specific target platform, with specific compiler, libraries, etc. and then NEVER CHANGE THEM. Or, (2) follow the rules of the language, even arcane ones that offend your sensibilities.