一段求数字%2模代码的反汇编

 

这是一段简单的代码,就一个数是否为奇偶的片段

1 int main()
2 {
3     int num ;
4     scanf("%d",&num);
5     num = num % 2;   // 这里求%2的模
6     printf("%d",num);
7     return 0;
8 }

反汇编代码如下:

.text:00401000 _main           proc near               ; CODE XREF: start+AFp
.text:00401000
.text:00401000 var_4           = dword ptr -4
.text:00401000
.text:00401000                 push    ecx
.text:00401001                 lea     eax, [esp+4+var_4]
.text:00401005                 push    eax
.text:00401006                 push    offset Format   ; "%d"
.text:0040100B                 call    _scanf
.text:00401010                 mov     eax, [esp+0Ch+var_4]
.text:00401014                 and     eax, 80000001h
.text:00401019                 jns     short loc_401020
.text:0040101B                 dec     eax
.text:0040101C                 or      eax, 0FFFFFFFEh
.text:0040101F                 inc     eax
.text:00401020
.text:00401020 loc_401020:                             ; CODE XREF: _main+19j
.text:00401020                 push    eax
.text:00401021                 push    offset Format   ; "%d"
.text:00401026                 mov     [esp+14h+var_4], eax
.text:0040102A                 call    sub_401040
.text:0040102F                 xor     eax, eax
.text:00401031                 add     esp, 14h
.text:00401034                 retn
.text:00401034 _main           endp

其中主要代码为:

.text:00401010                 mov     eax, [esp+0Ch+var_4]
.text:
00401014                 and     eax, 80000001h
.text:
00401019                 jns     short loc_401020
.text:0040101B                 dec     eax
.text:0040101C                 or      eax, 0FFFFFFFEh
.text:0040101F                 inc     eax
首先:

 1、因为有符号的数对2求模,只能有三种结果 -1 、0 、1;

2、编译器进行优化,and eax,80000001h 后,无论数字为多少,只会保留最高位和最低位。如果数字为奇数,最低位必然为1,同理,富豪为也会被保留下来

3、在通过jns short loc_401020进行判断符号位,符号位1(为负数),不跳转;符号位0(为正数),跳转。

4、对负数进行特殊处理,因为负数在内存中以补码的形式存放,就要讲第2步得出的结果进行修正,修正为补码形式,就是

     dec  eax
      or   eax, 0FFFFFFFEh
      inc  eax

举例1:经过第2步的出的结果为-1,即 1000 0001 ,当然,这个不是补码形式,就要把它换为补码形式( 1111 1111)

进行减1,1000 0000 ;然后同 0FFFF FFFEh进行位或运算,结果为1111 1110 ,所以,再加上一个1 ,即 1111 1111

举例2:经过第2步的出的结果为-0,即 1000 0000 ,当然,这个不是补码形式,就要把它换为补码形式( 1111 1111)

进行减1,0111 1111 ;然后同 0FFFF FFFEh进行位或运算,结果为1111 1111 ,所以,再加上一个1 ,即 0000 0000

 

 

 

下面是求一个数 %3的模代码

int main()
{
    int num ;
    scanf("%d",&num);
    num = num % 3;
    printf("%d",num);
    return 0;
}

反汇编代码如下:

 

00401000  /$  51            push ecx
00401001  |.  8D4424 00     lea eax,dword ptr ss:[esp]
00401005  |.  50            push eax
00401006  |.  68 30804000   push definevs.00408030                   ;  ASCII "%d"
0040100B  |.  E8 61000000   call definevs.00401071

00401010 |. 8B4424 08 mov eax,dword ptr ss:[esp+8] 00401014 |. B9 03000000 mov ecx,3 00401019 |. 99 cdq                      ;将寄存器扩展为 EDX:EAX 6位 0040101A |. F7F9 idiv ecx ;进行有符号数字的除法,商放EAX,余放EDX中
0040101C |. 52 push edx 0040101D |. 68 30804000 push definevs.00408030 ; ASCII "%d" 00401022 |. 895424 10 mov dword ptr ss:[esp+10],edx 00401026 |. E8 15000000 call definevs.00401040 0040102B |. 33C0 xor eax,eax 0040102D |. 83C4 14 add esp,14

 可见,除了就跟2的模外,其他的都会使用预先已有的除法指令进行!

posted @ 2012-08-17 11:21  xiaolongxia  阅读(238)  评论(0编辑  收藏  举报