在 C 程序中创建数据危险

标签 c assembly pipelining

我正在解决一个问题,我试图在不同的 C 程序中创建不同的场景,例如

  • 数据危险
  • 分支机构评估
  • 过程调用

这是为了学习管道和出现的不同危险。

所以我正在编写简单的 C 程序并反汇编为汇编语言,以查看是否会产生危险。但我不知道如何制造这些危险。你们知道我该怎么做吗?这是我编写的一些简单代码。

我使用编译。

gcc -g -c programName.c -o programName.o
gcc programName.o -o programName
objdump -d programName.o > programName.asm

代码:

#include <stdio.h>
int main()
{
    int i = 0;
    int size = 5;
    int num[5] = {1,2,3,4,5};
    int sum=0;
    int average = 0;

    for(i = 0; i < size; i++)
    {
        sum += num[i];
    }

    average=sum/size;

    return 0;
}

...这是其程序集。

average.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <main>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   c7 45 f0 00 00 00 00    movl   $0x0,0xfffffffffffffff0(%rbp)
   b:   c7 45 f4 05 00 00 00    movl   $0x5,0xfffffffffffffff4(%rbp)
  12:   c7 45 d0 01 00 00 00    movl   $0x1,0xffffffffffffffd0(%rbp)
  19:   c7 45 d4 02 00 00 00    movl   $0x2,0xffffffffffffffd4(%rbp)
  20:   c7 45 d8 03 00 00 00    movl   $0x3,0xffffffffffffffd8(%rbp)
  27:   c7 45 dc 04 00 00 00    movl   $0x4,0xffffffffffffffdc(%rbp)
  2e:   c7 45 e0 05 00 00 00    movl   $0x5,0xffffffffffffffe0(%rbp)
  35:   c7 45 f8 00 00 00 00    movl   $0x0,0xfffffffffffffff8(%rbp)
  3c:   c7 45 fc 00 00 00 00    movl   $0x0,0xfffffffffffffffc(%rbp)
  43:   c7 45 f0 00 00 00 00    movl   $0x0,0xfffffffffffffff0(%rbp)
  4a:   eb 10                   jmp    5c <main+0x5c>
  4c:   8b 45 f0                mov    0xfffffffffffffff0(%rbp),%eax
  4f:   48 98                   cltq   
  51:   8b 44 85 d0             mov    0xffffffffffffffd0(%rbp,%rax,4),%eax
  55:   01 45 f8                add    %eax,0xfffffffffffffff8(%rbp)
  58:   83 45 f0 01             addl   $0x1,0xfffffffffffffff0(%rbp)
  5c:   8b 45 f0                mov    0xfffffffffffffff0(%rbp),%eax
  5f:   3b 45 f4                cmp    0xfffffffffffffff4(%rbp),%eax
  62:   7c e8                   jl     4c <main+0x4c>
  64:   8b 55 f8                mov    0xfffffffffffffff8(%rbp),%edx
  67:   89 d0                   mov    %edx,%eax
  69:   c1 fa 1f                sar    $0x1f,%edx
  6c:   f7 7d f4                idivl  0xfffffffffffffff4(%rbp)
  6f:   89 45 fc                mov    %eax,0xfffffffffffffffc(%rbp)
  72:   b8 00 00 00 00          mov    $0x0,%eax
  77:   c9                      leaveq 
  78:   c3                      retq   

希望得到任何见解或帮助。谢谢!

最佳答案

由于这是家庭作业,我不会给你一个直接的答案,但会提供一些思考的内容来插入你走向正确的方向。

x86 是一个糟糕的 ISA,无法用来尝试和理解管道技术。一条 x86 指令可以隐藏两个或三个副作用,因此很难弄清给定指令在最简单的管道中的执行情况。您确定没有提供 RISC ISA 来解决此问题吗?

将循环/危险代码放入函数中,并最好随机化数组的创建。使阵列更长。一个好的编译器基本上会找出答案,并删除您编写的大部分代码!由于我不明白的原因,它将你的变量放入内存中。

一个好的编译器还会执行诸如循环展开之类的操作,以试图隐藏数据危险并获得更好的代码调度。了解如何克服这个问题(或者如果可以的话,给编译器一个标志,告诉它在允许乱搞编译器的情况下不要做这些事情)。

关键字“ volatile ”对于告诉编译器不要优化某些变量非常有帮助(它告诉编译器这个值可以随时改变,所以不要聪明地用它优化代码,而且不要将变量保留在寄存器文件中)。

数据危险意味着管道将停止等待数据。通常指令会被及时绕过,因此不会发生停顿。考虑哪些类型的指令可能无法被绕过并可能导致数据危险停顿。这取决于管道,因此在特定处理器上停顿的代码可能不会在另一个处理器上停顿。现代无序英特尔处理器非常擅长避免这些停顿,而编译器非常擅长重新调度代码,因此即使在有序核心上,它们也不会发生。

关于在 C 程序中创建数据危险,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26331703/

相关文章:

c - 如何使用 C 创建 TCP 套接字连接到预定义端口

assembly - 32位机中不是4倍数的内存地址可以到达吗?

python - Redis 流水线发送 200 条指令,只有 189 个答案

http - S3 是否支持 HTTP 流水线?

c - Fread 永远阻塞在带有命名管道的重定向标准输出上

c++ - 从 llvm pass 打印点文件

c - 如果它部分匹配字符串参数,如何从文件中返回特定行? [C]

c - 为什么c程序为未使用的局部变量保留空间?

c - 通过内联汇编交换 2 个指针

MIPS 结构性危害