VS2010中内联汇编入门--cdecl

水深无声 2023-10-11 10:30 98阅读 0赞

在vs2010中进行内联汇编时,注意在被调函数中,编译器自动在栈中为局部变量预留一个区域,如下面的反汇编代码所示,ebp-0xc0,并且初始化为0xcccccccc

  1. int __cdecl mse_sse(unsigned char * a, unsigned char * b, int len){
  2. 00B213B0 push ebp
  3. 00B213B1 mov ebp,esp
  4. 00B213B3 sub esp,0C0h
  5. 00B213B9 push ebx
  6. 00B213BA push esi
  7. 00B213BB push edi
  8. 00B213BC lea edi,[ebp-0C0h]
  9. 00B213C2 mov ecx,30h
  10. 00B213C7 mov eax,0CCCCCCCCh
  11. 00B213CC rep stos dword ptr es:[edi]

参数传递:

在cdecl调用下,参数由上层调用函数进行入栈,在内联汇编模式下,访问参数要用中括号加参数名称的方式获取参数

  1. mov esi,[a];//a
  2. 00B213CE mov esi,dword ptr [a]
  3. mov edi,[b];//b
  4. 00B213D1 mov edi,dword ptr [b]
  5. mov ecx,[len];//len
  6. 00B213D4 mov ecx,dword ptr [len]

不要使用下面的方式:

  1. mov esi,[ebp+8];//a
  2. mov edi,[ebp+8+4];//b
  3. mov ecx,[ebp+8+8];//len

这种方式在DEBUG下是正确的,但是在Release下会报错

下面是一个求MSE的小函数

  1. int __cdecl mse_sse(unsigned char * a, unsigned char * b, int len){
  2. __asm{
  3. /*
  4. mov esi,[ebp+8];//a
  5. mov edi,[ebp+8+4];//b
  6. mov ecx,[ebp+8+8];//len
  7. */
  8. mov esi,[a];//a
  9. mov edi,[b];//b
  10. mov ecx,[len];//len
  11. pxor xmm7,xmm7;//128bit 0
  12. movdqu xmm0,[esi];//a[0-7]
  13. punpcklbw xmm0,xmm7;//8bit->16bit
  14. movdqu xmm1,[edi];//b[0-7]
  15. punpcklbw xmm1,xmm7;//8bit->16bit
  16. psubw xmm0,xmm1;//a-b
  17. pabsw xmm0,xmm0; //|a-b|
  18. //movdqu [esi],xmm0
  19. pmullw xmm0,xmm0;//|a-b|^2
  20. phaddw xmm0,xmm0;//0,1->0
  21. phaddw xmm0,xmm0;//0,1,2,3->0
  22. phaddw xmm0,xmm0;//0,...,7->0
  23. movd eax,xmm0;
  24. }
  25. }

完整的代码:

  1. //fiel:main.c
  2. #include<stdlib.h>
  3. #include<stdio.h>
  4. #include"mem_align.h"
  5. #include "asm.h"
  6. struct sByte{
  7. char c;
  8. int i;
  9. } aa;
  10. int main(int argc, char * argv[])
  11. {
  12. int size =30;
  13. int align_size =16;
  14. //unsigned char * pVar_mem=(unsigned char *)(malloc(size+align_size));\
  15. //unsigned char * pVar = pVar_mem+(align_size-(int)pVar_mem&0xf);
  16. align_mem_get(pBuffer,30,16);
  17. struct sByte bb;
  18. unsigned char a[32]={0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7};
  19. unsigned char b[32]={0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7};
  20. int len = 8;
  21. int mse=mse_sse_v2(a,b,len);
  22. printf("mse = : %d \n",mse);
  23. mse=mse_sse(a,b,len);
  24. printf("mse = : %d \n",mse);
  25. printf("%d \n",sizeof(aa));
  26. printf("%d \n",sizeof(bb));
  27. printf("align_mem_get pBuffer : 0x%08x \n",(int)pBuffer);
  28. printf("align_mem_get pBuffer : 0x%08x mod 16 = %d \n",(int)pBuffer,(int)pBuffer%16);
  29. align_mem_free(pBuffer);
  30. return 0;
  31. }
  32. /*
  33. FILE: mem_align.h
  34. */
  35. #ifndef _MEM_AQLIGN_H_
  36. #define _MEM_AQLIGN_H_
  37. #define align_mem_get(pVar,size,align_size)\
  38. unsigned char * pVar_mem=(unsigned char *)(malloc(size+align_size));\
  39. unsigned char * pVar = pVar_mem+(align_size-(int)pVar_mem&0xf)
  40. #define align_mem_free(pVar) \
  41. free(pVar_mem); \
  42. pVar = 0
  43. #endif
  44. // asm.h
  45. #ifndef _ASM_H_
  46. #define _ASM_H_
  47. #include <xmmintrin.h>//SSE
  48. #include <emmintrin.h>//SSE2
  49. #include <pmmintrin.h>//SSE3
  50. #include <tmmintrin.h>//SSSE3
  51. #include <smmintrin.h>//SSE4.1
  52. #include <nmmintrin.h>//SSE4.2
  53. #include <immintrin.h>//AVX,AVX2,FMA
  54. //__declspec(naked) static int mse_sse(unsigned char * a, unsigned char * b, int len);
  55. int __cdecl mse_sse(unsigned char * a, unsigned char * b, int len);
  56. int __cdecl mse_sse_v2(unsigned char * a, unsigned char * b, int len);
  57. #endif
  58. //file:asm.c
  59. #include "asm.h"
  60. //8x8 16bit unsigned short
  61. //int __stdcall mse_sse(unsigned char * a, unsigned char * b, int len){
  62. //__declspec(naked) static int mse_sse(unsigned char * a, unsigned char * b, int len){
  63. int __cdecl mse_sse(unsigned char * a, unsigned char * b, int len){
  64. __asm{
  65. /*
  66. mov esi,[ebp+8];//a
  67. mov edi,[ebp+8+4];//b
  68. mov ecx,[ebp+8+8];//len
  69. */
  70. mov esi,[a];//a
  71. mov edi,[b];//b
  72. mov ecx,[len];//len
  73. pxor xmm7,xmm7;//128bit 0
  74. movdqu xmm0,[esi];//a[0-7]
  75. punpcklbw xmm0,xmm7;//8bit->16bit
  76. movdqu xmm1,[edi];//b[0-7]
  77. punpcklbw xmm1,xmm7;//8bit->16bit
  78. psubw xmm0,xmm1;//a-b
  79. pabsw xmm0,xmm0; //|a-b|
  80. //movdqu [esi],xmm0
  81. pmullw xmm0,xmm0;//|a-b|^2
  82. phaddw xmm0,xmm0;//0,1->0
  83. phaddw xmm0,xmm0;//0,1,2,3->0
  84. phaddw xmm0,xmm0;//0,...,7->0
  85. movd eax,xmm0;
  86. }
  87. }
  88. int __cdecl mse_sse_v2(unsigned char * a, unsigned char * b, int len){
  89. int x = (int)a;
  90. return len;
  91. }

【资料】比较好的说明: http://blog.csdn.net/kzh313561014/article/details/7283765

【GGC 下的 at&t 汇编】http://blog.csdn.net/zhangqingsup/article/details/6704253

发表评论

表情:
评论列表 (有 0 条评论,98人围观)

还没有评论,来说两句吧...

相关阅读

    相关 浅析VS2010汇编

    第一篇 1. 怎样进行反汇编 在调试的环境下,我们能够很方便地通过反汇编窗体查看程序生成的反汇编信息。 例如以下图所看到的。 [![image][]][image