Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 将加载的目标地址保留在寄存器中,直到指令失效_C_Assembly_Intel_Cpu Registers_Performancecounter - Fatal编程技术网

C 将加载的目标地址保留在寄存器中,直到指令失效

C 将加载的目标地址保留在寄存器中,直到指令失效,c,assembly,intel,cpu-registers,performancecounter,C,Assembly,Intel,Cpu Registers,Performancecounter,我想使用精确的基于事件的采样(PEBS)在XeonE5 Sandy桥上记录特定事件(例如缓存未命中)的所有地址 但是,《CoreTM i7处理器和英特尔至强5500处理器性能分析指南》第24页包含以下警告: 由于PEBS机制在以下位置捕获寄存器的值: 完成指令后,该指令的解引用地址 无法使用以下类型的加载指令(英特尔asm约定) 重建。MOV-RAX,[RAX+const]这种 指令主要与指针跟踪相关 mystruc=mystruc->next 这是该方法的一个显著缺点 获取内存指令地址的方法

我想使用精确的基于事件的采样(PEBS)在XeonE5 Sandy桥上记录特定事件(例如缓存未命中)的所有地址

但是,《CoreTM i7处理器和英特尔至强5500处理器性能分析指南》第24页包含以下警告:

由于PEBS机制在以下位置捕获寄存器的值: 完成指令后,该指令的解引用地址 无法使用以下类型的加载指令(英特尔asm约定) 重建。
MOV-RAX,[RAX+const]

这种 指令主要与指针跟踪相关
mystruc=mystruc->next
这是该方法的一个显著缺点 获取内存指令地址的方法

根据objdump,我的程序中有许多这种形式的加载指令有什么办法可以避免这些吗?

由于这是一个英特尔特有的问题,因此解决方案不必以任何方式进行移植,只需工作即可。我的代码是用C编写的,我正在寻找一个理想的编译器级解决方案(gcc或icc),但欢迎任何建议


一些例子:

mov    0x18(%rdi),%rdi

mov    (%rcx,%rax,8),%rax

在这两种情况下,在指令失效后(因此当我查看寄存器值以确定加载到/从何处加载时),地址的值(在这些示例中分别为
%rdi+18
%rcx+8*%rax
)被
mov

的结果覆盖。我现在能想到的唯一方法是使用&(与符号)汇编程序约束。这意味着,无论在哪里出现这样的指令,我都必须遍历我的代码,并替换掉所有取消引用
mystruc=mystruc->next的指针类似于:
asm volatile(“mov(%1),%0):“=&r”(mystruc):“r”(&(mystruc->next))


然而,这是一种非常普通的方法,并且可能存在比结构中的指针更复杂的情况。我知道这基本上增加了寄存器压力,因此编译器正在积极尝试避免这种情况,我仍在寻找其他方法来做到这一点。

您要做的是转换表单的所有指令:

mov    (%rcx,%rax,8),%rax
进入:


通过修改编译器生成的汇编程序源代码,可以更轻松地完成这项工作。下面是一个
perl
脚本,它将通过读取和修改
.s
文件来执行所有必要的转换

只需将构建更改为生成
.s
文件而不是
.o
文件,应用脚本,然后使用
as
gcc
生成
.o


这是实际的脚本。我已经在我自己的一些源代码上测试了它,遵循下面评论中的构建过程

该脚本具有以下功能:

  • 扫描并定位所有函数定义
  • 标识给定函数中使用的所有寄存器
  • 查找函数的所有返回点
  • 根据函数的寄存器用法选择要使用的临时寄存器(即,它将使用函数尚未使用的临时寄存器)
  • 用双指令序列替换所有“麻烦”指令
  • 在尝试使用被调用方保存的寄存器之前,尝试使用未使用的临时寄存器(例如,
    %r11
    或未使用的参数寄存器)
  • 如果所选寄存器被调用者保存,将添加
    push
    到函数prolog和
    pop
    到函数[multiple]
    ret
    语句
  • 维护所有分析和转换的日志,并将其作为注释附加到输出
    .s
    文件中

  • #/usr/bin/perl
    #pebsfix/pebsfixup——修复PEBS使用的汇编程序源代码
    #
    #命令行选项:
    #“-a”--仅使用完整的64位目标
    #“-l”--不要使用lea
    #“-D[diff file]”--显示差异(默认输出:“./diff”)
    #“-n10”--不要将寄存器%r10用作临时寄存器(默认为使用它)
    #“-o”--覆盖输入文件(可以是多个)
    #“-O”--输出文件(只允许一个.s输入)
    #“-q”--抑制警告
    #“-T[lvl]”--调试跟踪
    #
    #“-o”和“-o”是互斥的
    #
    #命令行脚本测试选项:
    #“-N[TPA]”--禁用临时寄存器类型[用于测试]
    #“-P”--强制推/弹出所有功能
    #
    #命令行参数:
    #1--要处理的.s文件列表[或要搜索的目录]
    #对于给定的文件“foo.s”,输出为“foo.TMP”
    #如果给出(-o),则将“foo.TMP”重命名为“foo.s”)
    #
    #建议用法:
    #更改生成以生成.s文件
    #发件人:
    #cc[选项]-c foo.c
    #致:
    #cc[options]-c-S foo.c
    #pebsfixup-o foo.s
    #cc-cfoo.s
    #
    #建议的编译器选项:
    #[可能只有在需要push/pop时才真正需要。使用-NP进行验证]
    #(1)使用以下任何一项:
    #-O2-fno优化同级呼叫
    #-O1
    #(2)使用-mno省略叶帧指针
    #(3)使用-mno红色区域[在任何情况下可能不需要]
    #
    #注:
    #(1)红色区域仅对叶函数(即如果fncA调用
    #fncB,fncA的红色区域将被摧毁)
    #(2)如果存在正式的堆栈框架,则推送到堆栈上不是问题
    #(3)如果函数的参数不超过六个(即。
    #不使用%rsp的正偏移量访问它们)
    #布拉格语
    使用严格的qw(vars接头);
    我们的$pgmtail;
    我们的$opt_a;
    我们的$opt\T;
    我们的$opt_D;
    我们的$opt_l;
    我们的$opt_n10;
    我们的$optn;
    我们的$opt_P;
    我们的$opt_q;
    我们的$opt_o;
    我们的$opt_O;
    我们的$opt_;
    我们的@reguse;
    我们的%reguse_tobase;
    我们的%reguse_isbase;
    我们的$regusergx;
    我们的@regtmplist;
    我们的%regtmp_类型;
    我们的$diff;
    我们的$sepflg;
    我们的美元是致命的;
    我们的@cmtprt;
    船长(@ARGV);
    出口(0);
    #主控——主控
    副船长
    {
    我的(@argv)=;
    我的($xfsrc);
    我的($file,@files);
    我的($bf);
    
    mov    (%rcx,%rax,8),%r11
    mov    %r11,%rax
    
    # function_original -- original function before pebsfixup
    # RETURNS: 23
    function_original:
        mov     $23,-4(%rsp)                # red zone code generated by compiler
        ...
        mov     -4(%rsp),%rax               # will still have $23
        ret
    
    # function_pebsfixup -- pebsfixup modified
    # RETURNS: 23
    function_pebsfixup:
        push    %r12                        # pebsfixup injected
    
        mov     $23,-4(%rsp)                # red zone code generated by compiler
        ...
        mov     -4(%rsp),%rax               # will still have $23
    
        pop     %r12                        # pebsfixup injected
        ret
    
    # function_inline -- function with inline asm block and red zone
    # RETURNS: unknown value
    function_inline:
        mov     $23,-4(%rsp)                # red zone code generated by compiler
    
        # inline asm block -- steps on red zone
        push    %rdx
        push    %rcx
        ...
        pop     %rcx
        pop     %rdx
    
        ...
    
        mov     -4(%rsp),%rax               # now -4(%rsp) no longer has $23
    
        ret
    
    mov     32(%rsp),%rax
    
    mov     40(%rsp),%rax