模运算、三目运算

来源:互联网 发布:知天下资源吗邀请码 编辑:程序博客网 时间:2024/05/19 02:04

模运算

int _tmain(int argc, _TCHAR* argv[]){    unsigned int uVar;    int nVar;    scanf("%d", &uVar);    scanf("%d", &nVar);    printf("%d\r\n", uVar % 16);    printf("%d\r\n", uVar % -16);    printf("%d\r\n", uVar % 9);    printf("%d\r\n", uVar % -9);    printf("%d\r\n", nVar % 16);    printf("%d\r\n", nVar % -16);    printf("%d\r\n", nVar % 9);    printf("%d\r\n", nVar % -9);    return 0;}

对非 2 的幂取模

VC6

在 VC6 中,无符号对非 2 的幂取摸,直接使用 idiv 或者 div 指令完成,所得结果(余数)存储在 edx 中。

这里写图片描述

定式为:

xor edx, edxmov reg, immdiv reg

VS

与 VC6 不同, 根据数学推导的公式:

ab=q...r

=>
r=aq×b

对此进行了优化,前三条指令计算所得结果 q

  • 当变量为无符号,模上正数时

这里写图片描述

定式为:

mov eax, Mmul Ashr edx, immlea reg, [edx * b]  ;此步骤有可能会用其他指令表示sub A, reg
  • 当变量为无符号,模上负数时

这里写图片描述

定式为:

mov eax, Mmul Ashr edx, immlea reg, [A + edx * (-b)]       ;此步骤为伪代码,可能会用其他指令
  • 当变量为有符号,模上正数时

这里写图片描述

定式为:

mov eax, Mimul Asar edx, immmov reg, edxshr reg, 1Fhadd reg, edxlea reg, [reg * b]      ;此步骤为伪代码,可能会用其他指令sub A, reg
  • 当变量为有符号,模上负数时:

这里写图片描述

定式为:

mov eax, Mimul Asar edx, immmov reg, edxshr reg, 1Fhadd reg, edxlea reg, [reg * (-b)]       ;此步骤为伪代码,可能会用其他指令替代sub A, reg

对 2 的幂取模

当变量为无符号

模上正数

这里写图片描述

若模上的数位 b,那么定式为:

and reg, (b + 1)

模上负数

这里写图片描述

直接使用了 div 指令

当变量为有符号

模上正数

这里写图片描述

这里加上跳转 jns 是为了区分变量是正负数的情况,若变量是正数,则需要跳转;如果变量是负数,则不需要跳转。定式为:

    and A, imm    jns NEW    dec A    or A, 0FFFFFFFFh    inc ANEW:

模上负数

这里写图片描述

假设 A % B,定式为:

cdqxor A, edxsub A, edx      ;此三步骤相当于 abs(a)and A, B            ;无论 A 为正负数,都作为正数取模xor A, edx      sub A, edx      ;如果 A 为正数,那么异或的结果仍是 A;如果 A 为负数,相当于对 A 求补 

三目运算

表达式 1 为简单比较;表达式 2 和 3 两者差值等于 1

int main(int argc, char* argv[]){    return argc == 5? 5 : 6;}

其反汇编代码如下:

这里写图片描述

假设三目运算为 Var == A ? B : C;那么,其定式为:

xor eax, eaxcmp Var, Asetxx aladd eax, B

关于 Set 指令,指的是根据 eflags 寄存器中的状态将目标操作数设置为 1 或 0

这里写图片描述

表达式 1 为简单比较;表达式 2 和 3 两者差值大于 1

int main(int argc, char* argv[]){    return argc == 5? 4 : 10;}

在 VC6 中,对此进行的优化:

这里写图片描述

示例解析:

mov eax, [esp + argc]sub eax, 5neg eaxsbb eax, eax这个时候,eax 的取值只可能为 0 或者 0xffffffffand eax, 6   如果此时 eax 为 0,and 后为 0;如果为 1,and 后为 6add eax, 4

但是在 VS 中,直接用 else…if 来替代。

原创粉丝点击