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 

 

 

你可能感兴趣的:(command)