C++ command buffer

以下代码实现了一个C++ command buffer,代码在VC80调试通过,支持_cdecl,_stdcall,_thiscall三种调用

1)参数存储:为了便于参数压栈,参数采用DWORD块存储,并且按照从右到左的顺序排列

2)参数进栈:使用计数循环,让每一个DWORD进栈

3)函数执行:对于_cdecl 需要手动退栈,_stdcall 和 _thiscall 自动退栈

4)未实现 check esp 和 sse优化

 

  1 #define OBJECT_ADDR_BIT (31)
  2 #define OBJECT_ADDR_MASK (1<<OBJECT_ADDR_BIT)
  3 
  4 #define AUTO_STACK_BIT (30)
  5 #define AUTO_STACK_MASK (1<<AUTO_STACK_BIT)
  6 
  7 #define PARAM_BLOCK_MASK (0xffff)
  8 
  9 unsigned int command_buffer[1024*1024]={0};
 10 unsigned int command_buffer_pos = 0;
 11 
 12 void test_cmd( int a,int b)
 13 {
 14      int c = a+b; 
 15 }
 16 
 17 void test_object_cmd( unsigned int object_addr,unsigned int func_addr,int a,int b )
 18 {
 19      int c = a+b; 
 20 }
 21 
 22 void test_stdcall_cmd_record( int a,int b )
 23 {
 24      command_buffer[command_buffer_pos++= (2&PARAM_BLOCK_MASK)|(AUTO_STACK_MASK); //参数块占有DWORD个数
 25      command_buffer[command_buffer_pos++= (unsigned int)(void*)&glVertex2i; //执行函数地址
 26      /*参数块按照倒序从右往左顺序排列*/
 27      command_buffer[command_buffer_pos++= b; //参数2
 28      command_buffer[command_buffer_pos++= a; //参数1
 29 }
 30 
 31 void test_cmd_record( int a,int b )
 32 {
 33      command_buffer[command_buffer_pos++= (2&PARAM_BLOCK_MASK)|(AUTO_STACK_MASK); //参数块占有DWORD个数
 34      command_buffer[command_buffer_pos++= (unsigned int)(void*)&test_cmd; //执行函数地址
 35      /*参数块按照倒序从右往左顺序排列*/
 36      command_buffer[command_buffer_pos++= b; //参数2
 37      command_buffer[command_buffer_pos++= a; //参数1
 38 }
 39 
 40 void test_object_cmd_record( unsigned int object_addr,unsigned int func_addr,int a,int b)
 41 {
 42      command_buffer[command_buffer_pos++= (2&PARAM_BLOCK_MASK)|OBJECT_ADDR_MASK|AUTO_STACK_MASK;//最高位表示是否包含对象地址
 43      command_buffer[command_buffer_pos++= func_addr; //执行函数地址
 44      /*参数块按照倒序从右往左顺序排列*/
 45      command_buffer[command_buffer_pos++= b; //参数2
 46      command_buffer[command_buffer_pos++= a; //参数1
 47      command_buffer[command_buffer_pos++= object_addr; //对象地址
 48 }
 49 
 50 void exec_command_buffer()
 51 {
 52      int i = 0;
 53      int c_command = 0;
 54  
 55      while( i<command_buffer_pos )
 56      {
 57           /* 第一个DWORD 的高16位表示是否包含对象地址,以及是否需要自动退栈;低16位表示 参数块所占用的DWORD数量 */
 58           unsigned int cc = command_buffer[i];
 59 
 60           /* 参数块所占用的DWORD数量*/
 61           int c = cc&0xffff;
 62   
 63           /* 第31位表示是否包含对象地址,如果包含对象地址,c1将用作1个DWORD的增量 */
 64           unsigned int c1 = (cc&0x80000000)>>31;
 65   
 66           /* 第30位表示是否需要手动退栈 */
 67           unsigned int c2 = (cc&0x40000000)>>30;
 68   
 69           int func_addr = command_buffer[i+1];
 70 
 71           /* 如果是_cdecl 调用,将用作esp增量 */
 72           int n = c*4;
 73 
 74           /* 对象地址 */
 75           int obj_addr = 0;
 76   
 77           /*判断是否包含对象地址*/
 78           if( c1 )
 79           {
 80                /* 对象地址包含在参数块的后面 */
 81                obj_addr = command_buffer[i+c+2]; 
 82           }
 83 
 84           _asm
 85           {
 86                mov eax,0
 87                mov ecx,c
 88                /* 参数进栈 */
 89           TARGET1:
 90 
 91                cmp eax,ecx
 92                jge TARGET2  
 93                mov ebx,i
 94                add ebx,2
 95                add ebx,eax
 96                /* 将一个DWORD进栈 */
 97                push dword ptr command_buffer[ebx*4]
 98                /* 计数循环并且跳转 TARGET1 */
 99                add eax,1 
100                jmp TARGET1 
101                /* 处理 _thiscall 的对象地址 */
102           TARGET2:
103 
104                mov ecx,c1
105                cmp ecx,0
106                je TARGET3
107                /* _thiscall 需要把对象地址放入ecx */
108                lea ecx,obj_addr   
109           TARGET3:
110 
111                call func_addr
112                /* 对于_thiscall和_stdcall不需要增加esp */
113                mov ecx,c2
114                cmp ecx,0
115                jne TARGET4
116                /* _cdecl 不需要增加esp */
117                add esp,n
118           TARGET4:
119 
120                nop
121           }
122   
123           /* 移动 buffer pos */
124           i += c+2+c1;
125   
126           /* 命令计数*/
127           c_command++;
128      }
129 }
130 
131 
132 

 

 

posted on 2008-11-14 16:22  cgwolver  阅读(1099)  评论(1编辑  收藏  举报

导航