Mirco said:
... but will eventually produce the gcc/as/unix variant.
OK, I figured out this part too, so (FWIW) I'll
post it. How's that appliable to the PerlMonks
contest? I don't really know (maybe somebody has a hint).
[start here]
....
use Inline C => qq{
// ==> inline
void by_asm(SV* no_zeros, SV* has_zeros)
{
STRLEN srclen, dstlen;
char *src = SvPV(SvRV(no_zeros), srclen);
char *dst = SvPV(SvRV(has_zeros), dstlen);
if( srclen < dstlen ) croak("block length mismatch!");
#ifdef _MSC_VER
_asm mov edi, dst
_asm mov esi, src
_asm mov ecx, dstlen
_asm xor eax, eax
_asm cld
start:
_asm repne scasb
_asm jne done
_asm mov edx, dstlen
_asm sub edx, ecx
_asm mov ah, byte ptr [-1+esi+edx]
_asm mov byte ptr [-1+edi], ah
_asm jmp start
done: ;
#else
__asm__ __volatile__(
"xorl %%eax, %%eax \\n\\t"
"cld \\n\\t"
"start: \\n\\t"
"repne \\n\\t"
"scasb \\n\\t"
"jne done \\n\\t"
"movl %[l], %%edx \\n\\t"
"subl %%ecx, %%edx \\n\\t"
"movb -1(%%esi,%%edx), %%ah \\n\\t"
"movb %%ah, -1(%%edi) \\n\\t"
"jmp start \\n\\t"
"done: \\n\\t"
: /* no output reg */
: "S"(src),"D"(dst),"c"(dstlen),[l]"m"(dstlen)
);
#endif
}
// <== inline
};
my $s_no_zeros = 'abcdefghijklmnopqrstuvwxyz';
my $s_has_zeros = 'abcdefghijklmnopqrstuvwxyz';
substr($s_has_zeros, 5, 1) = "\x0";
substr($s_has_zeros, -1, 1) = "\x0";
by_asm(\$s_no_zeros, \$s_has_zeros);
print "$s_no_zeros\n$s_has_zeros\n";
[end here]
Regards
M.