第七篇:逆向之循环数组队列

由于最近看了点除法优化的东西,这里就特意逆一个用取模比较多的程序吧,权当熟悉
版本: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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值