• Windows内核--内核汇编代码赏析: Rtl memory系列函数(3.3.1)


    找不到memcpy源代码?

            RtlXXXMemory宏和mem* 

                    

            搜索WRK源代码,找不到memxxx相关函数的源代码。它们在如下prebuilt lib库中。      

                    

            IDA工具查找ntoswrk.lib里memxxx函数的实现如下:

                    

    先从memchr开始      

    1. ; amd64 assemble
    2. .text:00000000004A51D0 ; void *__cdecl memchr(const void *Buf, int Val, size_t MaxCount)
    3. .text:00000000004A51D0 public memchr
    4. .text:00000000004A51D0 memchr proc near
    5. .text:00000000004A51D0 test r8, r8
    6. .text:00000000004A51D3 jz short loc_4A51E1
    7. .text:00000000004A51D5
    8. .text:00000000004A51D5 loc_4A51D5: ; CODE XREF: memchr+F↓j
    9. .text:00000000004A51D5 cmp [rcx], dl
    10. .text:00000000004A51D7 jz short loc_4A51E1
    11. .text:00000000004A51D9 inc rcx
    12. .text:00000000004A51DC dec r8
    13. .text:00000000004A51DF jnz short loc_4A51D5
    14. .text:00000000004A51E1
    15. .text:00000000004A51E1 loc_4A51E1: ; CODE XREF: memchr+3↑j
    16. .text:00000000004A51E1 ; memchr+7↑j
    17. .text:00000000004A51E1 xor eax, eax
    18. .text:00000000004A51E3 test r8, r8
    19. .text:00000000004A51E6 cmovnz rax, rcx
    20. .text:00000000004A51EA retn
    21. .text:00000000004A51EA memchr endp

            a. 为何出现r8/rcx/dl寄存器操作?

                    如上为amd64架构汇编,amd64 calling conversion默认函数前四个参数以rcx, rdx, r8 and r9传入。

    Bufrcx
    Valrdx
    MaxCountr8

            b. 汇编flow: test r8, r8判断r8, 如果是0:

                                                    跳到最后,eax清成0,再次判断r8是否是0,不为0,把rcx(Buf指针)赋值给rax, rax作为返回值返回。

                                            不是0:

                                                    比较*Buf和Val的低八位(以Byte单位),如相同,即找到字符位置,跳到最后返回,如不相同,Buf++, MacCount--, 重复开始的比较。

                                    

           工具生成 pseudo code

    1. void *__cdecl memchr(const void *Buf, int Val, size_t MaxCount)
    2. {
    3. void *result; // rax
    4. for ( ; MaxCount; --MaxCount )
    5. {
    6. if ( *(_BYTE *)Buf == (_BYTE)Val )
    7. break;
    8. Buf = (char *)Buf + 1;
    9. }
    10. result = 0i64; // 此处是工具解析的问题,可以先忽略
    11. if ( MaxCount )
    12. result = (void *)Buf;
    13. return result;
    14. }

          memchr没有什么特别的。

    memset

            常规意义上,memset会按byte去写,这样没有充分利用64bit硬件的单个指令高效性。

                    工具生成pseudo code:

                    ​​​​​​​        

                            首先判断是否超过8B, 超过就会优先按8B为单位去写。这里利用了 Val * 0x0101010101010101巧妙一次填充8个Val.

                                  eg:   ​​​​​​​

     memcpy

            为了尽可能减少以8字节为单位不断从内存(或CacheLine)中抓数据,内核实作优先采用更大的单位。

            32B:

                    

            4KB:

                    

                    prefetchnta指令可以实现跨页边界存取,非常强大。内核可能存在超过4KB数据量copy, 此指令相比常规的register大小为单位可以大幅提高性能。

             

  • 相关阅读:
    数字IC/FPGA面试题目合集解析——零
    微信小程序的在线课外阅读打卡记录系统uniapp
    Selenium安装报错:No matching distribution found for selenium。经个人尝试,问题已得到解决
    NLP(5)--自编码器
    自己实现httpsession
    实战Kaggle比赛:预测房价
    鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:Tabs)
    2333. 最小差值平方和-排序加二分查找,力扣c语言题解
    DBCO-PEG-Insulin|二苯并环辛炔-聚乙二醇-胰岛素|DBCO-PEG-胰岛素
    latex如何对.pdf格式的图片实现裁剪
  • 原文地址:https://blog.csdn.net/cxsjabcabc/article/details/127797351