由于最近看了点除法优化的东西,这里就特意逆一个用取模比较多的程序吧,权当熟悉
版本:Release
优化选项:O2
调试工具:OD
源码:
#include <stdio.h>
#include <stdlib.h>
#define FALSE 0
#define TRUE 1
#define MAX_SIZE 6
int capacity=MAX_SIZE;
enum {EXIT,ADD,DEL,SHOW};
typedef struct
{
int element;
}queue;
queue q[MAX_SIZE];
int front=-1,rear=-1;
int isempty()
{
return rear%capacity==(front+capacity)%capacity;
}
int isfull()
{
return (rear+1)%capacity==(front+capacity)%capacity;
}
int addq(int element)
{
if(isfull()==TRUE)
{
fprintf(stderr,"queue is full,auto redouble...\n");
return FALSE;
//redouble();
}
rear=(rear+1)%capacity;
q[rear].element=element;
return TRUE;
}
int deleteq()
{
if(isempty())
{
fprintf(stderr,"empty");
return FALSE;
}
front=(front+1)%capacity;
return TRUE;
}
void show()
{
int i;
if(isempty()==TRUE)
{
printf("empty\n");
return;
}
for(i=front+1;i!=(rear+1)%capacity;i=(i+1)%capacity)
printf("%d\t",q[i].element);
putchar('\n');
}
int main()
{
int chose;
int element;
while(TRUE)
{
printf("ADD 1\nDEL 2\nSHOW 3\nEXIT 0\n");
printf("please input chose: ");
scanf("%d",&chose);
fflush(stdin);
switch(chose)
{
case ADD:
printf("please input add element :");
scanf("%d",&element);
fflush(stdin);
if(addq(element)==TRUE)
printf("add success\n");
else
printf("add failed...\n");
break;
case DEL:
if(deleteq()==TRUE)
printf("del success\n");
else
printf("del failed\n");
break;
case SHOW:
show();
break;
case EXIT:
return 0;
default:
printf("input error\n");
break;
}
}
system("pause");
return 0;
}
主函数就把switch case主要跳转代码贴上来,OD自动加上的注释已经很多了就不说
00B91130 |> /68 3821B900 /push 00B92138 ; ASCII "ADD 1",LF,"DEL 2",LF,"SHOW 3",LF,"EXIT 0",LF
...................................
...................................
00B9115C |. |83F8 03 |cmp eax, 3 ; Switch (cases 0..3)
00B9115F |. |0F87 BB000000 |ja 00B91220
00B91165 |. |FF2485 3C12B9>|jmp dword ptr [eax*4+B9123C]
00B9116C |> |68 7021B900 |push 00B92170 ; ASCII "please input add element :"; Case 1 of switch 00B9115C
..............................
..............................
00B911EE |> |E8 0DFEFFFF |call deleteq ; Case 2 of switch 00B9115C
............................
..........................
00B91216 |> |E8 55FEFFFF |call show ; Case 3 of switch 00B9115C
............................
............................
00B9122A |.^\E9 01FFFFFF \jmp 00B91130
00B9122F ;这里就退出流程了
用于case跳转的分支表
00B9123C . \2F12B900 dd test.00B9122F ; 分支表 被用于 00B91165
00B91240 . 6C11B900 dd test.00B9116C
00B91244 . EE11B900 dd test.00B911EE
00B91248 . 1612B900 dd test.00B91216
addq函数代码
00B91184 |. A1 2030B900 |mov eax, dword ptr [rear] ; eax=rear
00B91189 |. 40 |inc eax ; rear++
00B9118A |. 99 |cdq ; 将rear扩展为64位(edx:eax)
00B9118B |. B9 06000000 |mov ecx, 6
00B91190 |. F7F9 |idiv ecx ; rear/6
00B91192 |. A1 1C30B900 |mov eax, dword ptr [front] ; eax=front
00B91197 |. 83C0 06 |add eax, 6 ; eax+=6
00B9119A |. BD 06000000 |mov ebp, 6
00B9119F |. 83C4 10 |add esp, 10
00B911A2 |. 8BCA |mov ecx, edx ; 将前面获得的余数存到ecx
00B911A4 |. 99 |cdq
00B911A5 |. F7FD |idiv ebp ; eax/6
00B911A7 |. 3BCA |cmp ecx, edx ; if(ecx!=edx) 将2次获得的余数相比较
00B911A9 |. 75 23 |jnz short 00B911CE
00B911AB |. 68 0421B900 |push 00B92104 ; ASCII "queue is full,auto redouble...",LF
00B911B0 |. FFD7 |call edi
00B911B2 |. 83C0 40 |add eax, 40 ; |
00B911B5 |. 50 |push eax ; |stream
00B911B6 |. FF15 A020B900 |call dword ptr [<&MSVCR90.fprintf>] ; \fprintf
00B911BC |. 83C4 08 |add esp, 8
00B911BF |. 68 9C21B900 |push 00B9219C ; ASCII "add failed...",LF
00B911C4 |. FFD6 |call esi
00B911C6 |. 83C4 04 |add esp, 4
00B911C9 |.^ E9 62FFFFFF |jmp 00B91130
00B911CE |> 8B5424 14 |mov edx, dword ptr [esp+14] ; esp+14处存储的是scanf输入的数
00B911D2 |. 68 8C21B900 |push 00B9218C ; ASCII "add success",LF
00B911D7 |. 890D 2030B900 |mov dword ptr [rear], ecx ; rear = ecx
00B911DD |. 89148D 7C33B9>|mov dword ptr [ecx*4+q], edx ; q[rear]=[esp+14],即真正的入队操作
00B911E4 |. FFD6 |call esi
下面是deleteq函数
00B91000 >/$ 8B0D 2030B900 mov ecx, dword ptr [rear] ; ecx=rear
00B91006 |. B8 ABAAAA2A mov eax, 2AAAAAAB ; 下面几个指令是取模优化,这个16进制数用小数方式来计算大概是0.16左右的值,其实源码也就是1/6了
00B9100B |. F7E9 imul ecx
00B9100D |. 8BC2 mov eax, edx
00B9100F |. C1E8 1F shr eax, 1F
00B91012 |. 03C2 add eax, edx ; 这里eax即为rear/6的结果
00B91014 |. 8D0440 lea eax, dword ptr [eax+eax*2]
00B91017 |. 03C0 add eax, eax
00B91019 |. 56 push esi
00B9101A |. 8B35 1C30B900 mov esi, dword ptr [front]
00B91020 |. 2BC8 sub ecx, eax ; 这里ecx才是真正取模的结果
00B91022 |. 8D46 06 lea eax, dword ptr [esi+6] ; 先加6再取模
00B91025 |. 57 push edi
00B91026 |. 99 cdq
00B91027 |. BF 06000000 mov edi, 6
00B9102C |. F7FF idiv edi
00B9102E |. 3BCA cmp ecx, edx ; if ((front+6)%6)!=(rear%6)
00B91030 |. 75 1D jnz short 00B9104F
00B91032 |. 68 2421B900 push 00B92124 ; ASCII "empty"
00B91037 |. FF15 AC20B900 call dword ptr [<&MSVCR90.__iob_func>] ; MSVCR90.__p__iob
00B9103D |. 83C0 40 add eax, 40 ; |
00B91040 |. 50 push eax ; |stream
00B91041 |. FF15 A020B900 call dword ptr [<&MSVCR90.fprintf>] ; \fprintf
00B91047 |. 83C4 08 add esp, 8
00B9104A |. 5F pop edi
00B9104B |. 33C0 xor eax, eax
00B9104D |. 5E pop esi
00B9104E |. C3 retn
00B9104F |> 8D46 01 lea eax, dword ptr [esi+1] ; front=(front+1)%6
00B91052 |. 99 cdq
00B91053 |. 8BCF mov ecx, edi
00B91055 |. F7F9 idiv ecx
00B91057 |. 5F pop edi
00B91058 |. B8 01000000 mov eax, 1
00B9105D |. 5E pop esi
00B9105E |. 8915 1C30B900 mov dword ptr [front], edx
00B91064 \. C3 retn
最后一个show函数有兴趣自己看看吧,就加点提示不多注释了
00B91070 >/$ 8B0D 2030B900 mov ecx, dword ptr [rear] ; rear%6!=(front+6)%6
00B91076 |. B8 ABAAAA2A mov eax, 2AAAAAAB
00B9107B |. F7E9 imul ecx
00B9107D |. 8BC2 mov eax, edx
00B9107F |. C1E8 1F shr eax, 1F
00B91082 |. 03C2 add eax, edx
00B91084 |. 53 push ebx
00B91085 |. 8D0440 lea eax, dword ptr [eax+eax*2]
00B91088 |. 56 push esi
00B91089 |. 8B35 1C30B900 mov esi, dword ptr [front]
00B9108F |. 03C0 add eax, eax
00B91091 |. 57 push edi
00B91092 |. 8BF9 mov edi, ecx
00B91094 |. 2BF8 sub edi, eax
00B91096 |. 8D46 06 lea eax, dword ptr [esi+6]
00B91099 |. 99 cdq
00B9109A |. BB 06000000 mov ebx, 6
00B9109F |. F7FB idiv ebx
00B910A1 |. 3BFA cmp edi, edx
00B910A3 |. 75 12 jnz short 00B910B7
00B910A5 |. 68 2C21B900 push 00B9212C ; /format = "empty",LF,""
00B910AA |. FF15 A420B900 call dword ptr [<&MSVCR90.printf>] ; \printf
00B910B0 |. 83C4 04 add esp, 4
00B910B3 |. 5F pop edi
00B910B4 |. 5E pop esi
00B910B5 |. 5B pop ebx
00B910B6 |. C3 retn
00B910B7 |> 8D41 01 lea eax, dword ptr [ecx+1] ; front+1!=rear+1%6
00B910BA |. 99 cdq
00B910BB |. 8BCB mov ecx, ebx
00B910BD |. F7F9 idiv ecx
00B910BF |. 46 inc esi
00B910C0 |. 3BF2 cmp esi, edx
00B910C2 |. 74 35 je short 00B910F9
00B910C4 |. 8B3D A420B900 mov edi, dword ptr [<&MSVCR90.printf>] ; MSVCR90.printf
00B910CA |. 8D9B 00000000 lea ebx, dword ptr [ebx]
00B910D0 |> 8B14B5 7C33B9>/mov edx, dword ptr [esi*4+q]
00B910D7 |. 52 |push edx
00B910D8 |. 68 3421B900 |push 00B92134 ; ASCII "%d",TAB
00B910DD |. FFD7 |call edi
00B910DF |. 8D46 01 |lea eax, dword ptr [esi+1] ; front=(front+1)%6
00B910E2 |. 99 |cdq
00B910E3 |. 8BCB |mov ecx, ebx
00B910E5 |. F7F9 |idiv ecx
00B910E7 |. A1 2030B900 |mov eax, dword ptr [rear]
00B910EC |. 40 |inc eax
00B910ED |. 83C4 08 |add esp, 8
00B910F0 |. 8BF2 |mov esi, edx
00B910F2 |. 99 |cdq
00B910F3 |. F7F9 |idiv ecx
00B910F5 |. 3BF2 |cmp esi, edx
00B910F7 |.^ 75 D7 \jnz short 00B910D0
00B910F9 |> 6A 0A push 0A ; /c = 0A (Line Feed)
00B910FB |. FF15 9C20B900 call dword ptr [<&MSVCR90.putchar>] ; \putchar
00B91101 |. 83C4 04 add esp, 4
00B91104 |. 5F pop edi
00B91105 |. 5E pop esi
00B91106 |. 5B pop ebx
00B91107 \. C3 retn