除法终于整理结束了,这篇开始整理取模运算,对于取模运算来说,个别的情况还是需要使用除法的,所以除法运算的基础还是得牢靠。
取模也叫取余,表达为 a % b。下面需要对b的情况进行区分来分析
1. 变量
2. 常量
2.1 无符号
2.1.1 2的幂
2.1.2 非2的幂
2.2 有符号
2.1.1 2的幂
2.1.1.1 正数
2.1.1.2 负数
2.1.2 非2的幂
首先,这里和除法一样,对于为变量时候,都是没有优化的,所以直接会使用div/idiv指令,可以据此判断出有无符号,取模的结果在edx中。
下面主要探讨常量的情况,先来补充一点基础知识,先看如下代码
printf("%d\r\n",8%3);
printf("%d\r\n",8%-3);
printf("%d\r\n",-8%3);
printf("%d\r\n",-8%-3);
上面的运算结果
2
2
-2
-2
如果对于结果有误的可以看下面的公式
设被除数为a,除数为b,商为q,余数为r
a / b = q ..余.. r
=> a = q*b + r
=> r = a - q*b; //求余公式
也就是说余数等于被除数减去商乘以除数,这里应该比较好理解。这里对于某些情况中,取模也会使用该公式进行优化。
我们挑最后第三个来套一下公式看是否正确,剩余几个同理可求得
-8%3
已知除法向零取整,-8/-3可得商q=-2
r = a - q*b
= -8 - -2*3
= -8 + 6
= -2
OK,其实对于上面的结果来说,其实我们还可以得出一个规律,就是余数的符号跟着被除数走,这里的应用具体后面会提。
好了,下面来看2.1.1情况,也就是无符号中2的幂情况,对于无符号的情况,debug都不优化,主要来看release中的情况
int main(unsigned int argc, char* argv[])
{
printf("%d",argc%8);
return 0;
}
对应汇编代码
.text:00401043 mov eax, [ebp+argc]
.text:00401046 and eax, 7
.text:00401049 push eax
可以发现,其取模的结果就用了一个and 7,下面我们来分析一下<