memset 的实现分析

  • 时间:
  • 浏览:1
  • 来源:彩神大发幸运飞艇_神彩大发幸运飞艇官方

  void* __cdecl memset (void* _Dst, int _Val, size_t _Size);

  本文讨论的前提条件是:操作系统平台为 windows 系统,编译器为 VS1005 中的 VC,编译输出选项主要为 Release,反汇编工具为 VC 四种 和 IDA。下面将给出有些经过实际观察和分析得到的基本结论,

  memset 是 msvcrt.dll (什儿 Dll 有名称不同的多个版本)中的有有有二个多导出函数,但由于写有有有二个多简单的程序作为观察,编译器将不要再让目标程序导入对应的 Dll,然后把 memset 直接插入到目标程序的代码段。

  什儿 看法首先是毫无道理的,在代码风格,可读性,可维护性上根本不构成有有有二个多命题,且 memset 在开发中的使用是非常常见的。什儿 错误观点来自于对代码风格和语言的僵硬理解,然后 我们歌词 歌词 将看完在编译器正确处理后两者的等效性。

  memset(a, 0, sizeof(a));

  (3.2)主要循环累积 rep stosd 串存储指令,以 DWORD (4 bytes) 为基本单位循环设置。

  下面给出的是 memset 在 IDE 中的汇编代码,来自于 Micrsoft Visual Studio X\VC\crt\src\intel\memset.asm 的内容(下面的汇编代码在以字节为单位时使用的是 MOV [EDI], AL, 而在实际编译结果中是 rep stosb):

  下面给出的是 _VEC_memzero 的汇编代码:

  第六个参数确实为 int 类型,怎么让函数针对的目标是字节,很多很多很多很多有它实际上提供的是有有有二个多字节的值。首先给出该函数的常规实现过程(上面我们歌词 歌词 将分析在 CPU 支持 sse2 时的分支)的基本结论:

  这里分析 memset 什儿 函数在汇编语言层面的实现最好的依据。首先,memset 的原型如下:

  上面的代码相对简单,这里就不全部解释了。可不要再能 看完有有有有二个多名为 _VEC_memset 的标签(是有有有二个多具体函数)在满足条件时接管了此函数。即当同時 满足:(1)_Val 为 0;(2) CPU 支持 SSE2,(3)_Size 达到某个阈值(这里是256字节)时,memset 由于跳转到 _VEC_memzero 分支。

  关于 SSE2,我将引用 Intel 的文档内容简要介绍如下:

  由于把所有元素赋值为 -1 ( signed ) / 最大值 (unsigned) , 可不要再能 用 memset (a, 0xFF, sizeof ( a ));

  【补充】在讨论然后 ,还要先明确有有有二个多基本常识,即 memset 中提供的那个填充值的参数,是以字节为单位填充内存,怎么让实际的 memset 正确处理中只把它当作字节正确处理(即没人 0-7 bit 重要,高位被忽略),将其低位字节扩展成 32 位(累似 参数值为 0x12345678,则实际被扩展成 0x78787878),怎么让用 rep stosd 填充。怎么让 memset 没人 像循环赋值一样,完成对内存完成 4 bytes 为周期的周期性填充(而没人 把所有字节都赋值为相同值),但汇编语言可不要再能 。

  什儿 情况表的汇编代码比较简单,怎么让忽略。根据什儿 点可不要再能 看完,不论在代码风格层面还是运行下行强度 层面,认为使用初始化列表优于 memset 都是四种 毫无理由的主观臆测。事实上,两者在运行下行强度 上等效,且代码风格上不所处优劣之分。很多很多很多很多有,当程序员对行态体,数组进行初始化时,不还要在这里产生犹豫。上面我们歌词 歌词 回会看完,对数组用循环的最好的依据初始化,和调用 memset 初始化,在多数条件下的等效性。

  (3.3)由于还有有些字节(1~3 bytes)未被设置,则以字节为单位循环设置。

  (3.1)由于 _Dst 没人 对齐到 DWORD,则先把前面未对齐累积(1~3 bytes),以字节为单位循环设置。

  (3)memset 的实现。

  SSE2 在 Pentium 4 和 Intel Xeon 正确处理器中引入,提高了 3-D 图形,视频编码解码,语音识别,互联网,科学技术和工程程序的性能。提供 128-bit 的数据类型和相关指令,8 个 128-bit XMM 寄存器(XMM0~XMM7)。上面可不要再能 看完,当 CPU 支持 SSE2 时,memset 将采用 SSE2 进行批量设置,每条指令可赋值 16 Bytes。

  SSE2 全称是 Streaming SIMD Extention2, SIMD 全称是 Single-Instruction, Multiple-Data,是 Intel MMX 技术支持的四种 单指令多数据运行模型,其目的为提高多媒体和通讯程序的性能。

  怎么让,假设有有有有二个多整数数组 a[],由于把所有元素赋值为 0,可不要再能 用 memset (a, 0, sizeof ( a )); // 这由于是 memset 使用中最常见的情况表

  int a[100] = { 1, 2 };

  (1)在数组被声明时提供初始化列表(且语言上仅能在声明时提供),其语法定义时对于缺省元素将使用 0 填充。在 MSVC 编译器的 release 输出中,将后续元素使用 memset 进行初始化。

  memset 是 msvcrt 中的有有有二个多函数,其作用和用途是显而易见的,通常是对一段内存进行填充,就其作用四种 不具有任何歧义性。但都是人一定要纠结对数组的初始化一定要写成如下形式:

  由于多媒体数据正确处理的行态是,常见在血块的小元素(BYTE,WORD,DWORD 等)组成的连续数据上进行相同的操作,很多很多很多很多有可不要再能 在根小指令中提高数据吞吐能力来提高下行强度 (即每次把多个数据打包成一组进行相同的并行操作),即 SIMD。(我的解释性评论,2014年5月3日补充 -- hoodlum19100)

  int a[...] = { 0 };

  而认为如下使用 memset 的写法不明就里的被其排斥和拒绝:

  以上是 memset 的最好的依据的过程,上面我们歌词 歌词 将看完当 CPU 支持 SSE2 时的分支和上述步骤相同,然后第二步中基本单位的粒度更大(128 bit / 16 bytes)。

  通过 CPUID.01H (EAX=01H) 指令,由于 EDX.SSE2 [ bit 26 ] = 1,则支持 SSE2 扩展。

  (2)对数组用循环初始化时(这里假设数组元素类型为 int),编译器将其正确处理为 rep stosd 指令。

  由于要把所有元素赋值为任意有有有二个多常数值,则 memset 没人 达到要求,还要用高级语言的循环进行赋值。

  -- hoodlum19100 on 2014年6月19日 补充。