1

I am working on a problem where I am attempting to create different scenarios in different C programs such as

  • Data Hazard
  • Branch Evaluation
  • Procedure Call

This is in an attempt at learning pipelining and the different hazards that come up.

So I am writing simple C programs and disassembling to assembly language to see if a hazard gets created. But I cannot figure out how to create these hazards. Do yall have any idea how I could do this? Here is some of the simple code I have written.

I compile using.

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

Code:

#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;
}

...and here is the assembly for that.

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   

Would appreciate any insight or help. Thanks!

4

1 回答 1

1

由于这是作业,我不会给你一个直接的答案,而是一些深思熟虑的东西,以推动你朝着正确的方向前进。

x86 是一个糟糕的 ISA,用于尝试和理解流水线。一条 x86 指令可以隐藏两个或三个副作用,即使是最简单的流水线,也很难弄清给定指令的执行情况。你确定你没有提供一个 RISC ISA 来解决这个问题吗?

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

一个好的编译器也会做一些事情,比如循环展开,以试图隐藏数据危险并获得更好的代码调度。学习如何解决这个问题(或者如果可以的话,给编译器一个标志,告诉它如果允许乱搞编译器就不要做这些事情)。

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

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

于 2014-10-13T11:41:03.177 回答