January 25, 2003
The function below is not compiled correctly: without the line after 'L1:' the result value is not put in EAX, with it it gets set twice

int memcmp(void* src, void* dst, uint count) {
   asm {
      mov   ECX, count        ;  /* ECX = count */
      mov   EDI, dst          ;
      mov   ESI, src          ;

      repe              ;
      cmpsb             ;  /* for now, byte wise */
      jz L1             ;  /* if z, compare was ok -> ECX == 0 */
      sub   count, ECX  ;  /* convert to index of failing byte */
L1:   mov   EAX, count  ;  /* without this, eax is not set. With this, it's
set twice! */
   }
   return count;
}


February 04, 2003
Strange as it seems, this is not a bug. In D, the last argument is passed in EAX, in this case, 'count' is passed to memcmp() in EAX. Since EAX is not modified in the function, EAX is the same as 'count' upon return, and so is not reloaded.

When the line assigning 'count' to EAX is added, the code generator marks EAX as modified, and so 'count' gets reloaded into EAX by the 'return count;' statement.

Granted, the inline assembler could be smarter about just how EAX is modified and avoid the redundant load, but the correct result still happens. Also, I know of no other inline assembler that even keeps track of which registers are modified (what they do is just stupidly assume all registers are modified, which results in lousy prolog/epilog code, or they (i.e. gcc) require the programmer to note which ones are modified, which is very error prone).

The solution to this particular code is to leave off the EAX load at the end, and let the compiler take care of it with the 'return count;' statement.

"Jeroen van Bemmel" <anonymous@somewhere.com> wrote in message news:b0v1jj$2rpa$1@digitaldaemon.com...
> The function below is not compiled correctly: without the line after 'L1:' the result value is not put in EAX, with it it gets set twice
>
> int memcmp(void* src, void* dst, uint count) {
>    asm {
>       mov   ECX, count        ;  /* ECX = count */
>       mov   EDI, dst          ;
>       mov   ESI, src          ;
>
>       repe              ;
>       cmpsb             ;  /* for now, byte wise */
>       jz L1             ;  /* if z, compare was ok -> ECX == 0 */
>       sub   count, ECX  ;  /* convert to index of failing byte */
> L1:   mov   EAX, count  ;  /* without this, eax is not set. With this,
it's
> set twice! */
>    }
>    return count;
> }
>
>