Consider a function that calls another function and checks for error. Assume that the function CheckError()
returns 0 on failure, and other numbers indicates success.
First version: taken branch for success or fall through to the error processing code (which is in the middle of the function).
CALL CheckError
TEST EAX,EAX ;check if return value is 0
JNZ Normal
ErrorProcessing:
... ;some error processing code here
Normal:
... ;some usual code here
Second version taken branch on error, or fall through to the normal path. The error processing code is at the end of the function.
CALL CheckError
TEST EAX,EAX
JZ ErrorProcessing
Normal:
... ;some usual code here
ErrorProcessing:
... ;some error processing code here
Which one of these two methods is better? Why?
Personally, I think first code has better code structure (more readable and programmable), because the code is compact. However, I also think that the second code has better speed normally (in the no-error case), because a not-taken conditional jump takes 2-3 clock cycles (maybe I'm too picky here) less than a taken one.
Anyway, I found that all compilers I tested use the first model when it compilers an if
statement. For instance:
if (GetActiveWindow() == NULL)
{
printf("Error: can't get window's handle.\n");
return -1;
}
printf("Succeed.\n");
return 0;
This should compile to (without any exe entry routine):
CALL [GetActiveWindow] ;if (GetActiveWindow() == NULL)
TEST EAX,EAX
JNZ CodeSucceed
;printf("Error.......\n"); return -1
PUSH OFFSET "Error.........\n"
CALL [Printf]
ADD ESP,4
OR EAX,0FFFFFFFFH
JMP Exit
CodeSucceed: ;printf("Succeed.\n"); return 0
PUSH OFFSET "Succeed.\n"
CALL [Printf]
ADD ESP,4
XOR EAX,EAX
Exit:
RETN