Quote Originally Posted by awsdert View Post
As for the mul here's a psuedo example using made up byte code (with the assumption only 1 or 0 are the result of the comparison)

Code:
01 01 00000006 # mov %1,00000006 ; Fill register 1 with value of 6
01 01 00000006 # mov %2,00000006 ; Fill register 2 with value of 6
02 12 # cmp %1,%2 ; Compare register 1 to register 2, result will be placed in register 0
03 10 # mul  %1,%0 ; Multiply register 1 by register 0, 0 * %1 = 0, 1 * %1 = %1
04 01 # add %ac,%1 ; Add to address counter value of register 1
05 02 00000002 # add %2,00000002 ; Add to register 2 the value 2
05 02 0000001E # add %2,0000001E ; Add to register 2 30 (character '0')
06 02 # mov %0,%2 ; Fill register 0 with value of register 2
07 00000001 # syscall putchar ; print value of register 0 as next character
In this example '8' would be printed since register 1 and register 2 are equal resulting in the comparison putting value 0 into register 0 which when multiplied against register 1 results in 0 which when used by the add instruction would result in nothing being added to the address counter which results in the add 2 to register 2 being executed which then continues onto add '0' as it would've done anyway if the address counter had 6 added to it had the result of the comparison been 1, notice that at no point there does the CPU have to wait for new instructions to be loaded on the "branch" as it sees no branch to begin with, at most it just ignores the already loaded 6 bytes worth of information and just continues on with the next loaded information. Now granted this particular example does not take into account comparisons that result in anything other than 0 or 1 so would actually be quite dangerous to use without first clearing unwanted bits via the and instruction
And, again, it makes no sense. What is being done with this "address counter"? Is it a "program counter" or "instruction pointer"? In that case this "add %ac,%1" is nothing else but an indirect jump and succetible to the rules of dynamic branch prediction, which is worse than conditional jumps (they follow "static rules").

You realize this MUL, in this context, is actualy an AND and this CMP is simply a subtraction?

If it is possible to avoid branches, the compiler will do it for you. Like this:
Code:
; if ( a > b ) b = a;
;
; Suppose a is in EAX and b is in EDX:
cmp eax,edx
cmovg edx,eax
No need for bogus multiplications and indirect jumps. If it is not possible the compiler will choose a less damaging code. For exemplo:

Code:
;while ( size-- ) *p++ = 0;
;
; Supose size is in ECX and p is in RDX register.
...
  jmp  .test           ; not subject of branch prediction.
.loop:
  dec ecx
  mov byte [rdx],0
  inc rdx
.test:
  test ecx,ecx
  jnz .loop          ; no penalty for jumps backwards!
...
By the way, other processors have conditional moves as well... ARM is another example.