#!/usr/local/bin/perl # Copyright(C) TAKASUGI Shinji (ts@sf.airnet.ne.jp) binmode STDOUT; $unsigned_scale = 2 ** 32; $signed_scale = 2 ** 31; sub powerOf2Signed { local($shift) = @_; if ($shift == 1) { print " cdq\n", " sub eax, edx\n", " sar eax, $shift\n"; } else { print " cdq\n", " shr edx, ", 32 - $shift, "\n", " add eax, edx\n", " sar eax, $shift\n"; } } print "Content-Type: text/html\n\n"; exit 0 if $ENV{'REQUEST_METHOD'} eq 'HEAD'; foreach (split('&', $ENV{'QUERY_STRING'})) { ($key, $value) = split('=', $_, 2); $value =~ tr/+/ /; $value =~ s/%(..)/pack('C', hex($1))/ge; $param{$key} = $value; } $div = $param{'divisor'}; $errormsg = "Invalid divisor!!\n"; print '
| dividend: | eax', ' |
| divisor: | ', $div, ' |
| quotient: | eax', ' |
', "\n";
if (!$div || $div != int($div))
{ print $errormsg;
}
elsif ($div =~ /^\d/) # unsigned
{ if ($div >= $unsigned_scale)
{ print $errormsg;
}
elsif (!($div & ($div - 1))) # power of 2
{ $shift = 0;
$shift++ while ($div = $div >> 1) > 0;
$shift && print " shr eax, $shift\n";
}
elsif ($div >= 0x80000000)
{ print " cmp eax, $div\n",
" sbb eax, eax\n",
" inc eax\n";
}
else
{ $shift = 0;
$remainder = ((2 ** 31 - 1) % $div + 1) * 2 % $div; # do not exceed integer limit!
while ($remainder && (2 ** $shift < $div - $remainder))
{ $shift++;
$remainder = $remainder * 2 % $div;
}
$multiplier = (2 ** (32 + $shift) + ($div - $remainder) % $div) / $div;
if ($multiplier < $unsigned_scale)
{ $multiplier = sprintf('%x', $multiplier);
$multiplier =~ s/^(\D)/0$1/;
print " mov edx, ${multiplier}h\n",
" mul edx\n",
" mov eax, edx\n";
$shift && print " shr eax, $shift\n";
}
else
{ $multiplier = sprintf('%x', $multiplier - $unsigned_scale);
$multiplier =~ s/^(\D)/0$1/;
print " mov edx, ${multiplier}h\n",
" mov ecx, eax\n",
" mul edx\n",
" mov eax, edx\n",
" add eax, ecx\n";
if ($shift)
{ print " rcr eax, 1\n";
$shift >= 2 && print " shr eax, ", $shift - 1, "\n";
}
}
}
}
else # signed
{ $absdiv = abs($div);
if ($div >= $signed_scale || $div < -$signed_scale)
{ print $errormsg;
}
elsif (!($absdiv & ($absdiv - 1))) # power of 2
{ if ($div > 0) # signed positive
{ $shift = 0;
$shift++ while ($absdiv = $absdiv >> 1) > 0;
$shift && &powerOf2Signed($shift);
}
else # signed negative
{ $shift = 0;
$shift++ while ($absdiv = $absdiv >> 1) > 0;
$shift && &powerOf2Signed($shift);
print " neg eax\n";
}
}
else
{ $shift = 0;
$remainder = 2 ** 30 % $absdiv * 2 % $absdiv * 2 % $absdiv; # do not exceed integer limit!
if ($div > 0)
{ while (2 ** ($shift + 1) < $absdiv - $remainder)
{ $shift++;
$remainder = $remainder * 2 % $absdiv;
}
}
else
{ while (2 ** ($shift + 1) <= $absdiv - $remainder)
{ $shift++;
$remainder = $remainder * 2 % $absdiv;
}
}
$multiplier = (2 ** (32 + $shift) + ($absdiv - $remainder)) / $absdiv;
$multiplier = ~$multiplier + 1 if $div < 0;
if ($div > 0 && $multiplier < $signed_scale
|| $div < 0 && $multiplier >= $signed_scale)
{ $multiplier = sprintf('%x', $multiplier);
$multiplier =~ s/^(\D)/0$1/;
print " mov edx, ${multiplier}h\n",
" imul edx\n",
" mov eax, edx\n",
" sar edx, 31\n";
$shift && print " sar eax, $shift\n";
print " sub eax, edx\n";
}
else
{ $multiplier = sprintf('%x', $multiplier);
$multiplier =~ s/^(\D)/0$1/;
print " mov edx, ${multiplier}h\n",
" mov ecx, eax\n",
" imul edx\n",
" mov eax, edx\n",
" sar edx, 31\n",
$div > 0 ? " add eax, ecx\n" : " sub eax, ecx\n";
if ($shift)
{ print " rcr eax, 1\n";
$shift >= 2 && print " sar eax, ", $shift - 1, "\n";
print " sub eax, edx\n";
}
}
}
}
print '