What is the reason behind this?
First of all, out of bounds array access is undefined behavior. So your first access to a which is a[-1][3] is not valid. 
But to your question what is happening there:
You can imagine your:
int a[3][3] = {
  {0, 1, 2}, 
  {3, 4, 5},
  {6, 7, 8}
};
to have this layout in your system memory:
+---+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
+---+---+---+---+---+---+---+---+---+
Your [-1] in a[-1][3] points three elements before your arr array.
 arr[-1]     arr[0]      arr[1]
  ↓           ↓           ↓
+---+---+---+---+---+---+---+---+---+---+---+---+
| ? | ? | ? | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
+---+---+---+---+---+---+---+---+---+---+---+---+
With [3] in a[-1][3] you try to access the element at index 3 from that position.
  0   1   2   3
+---+---+---+---+---+---+---+---+---+---+---+---+
| ? | ? | ? | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
+---+---+---+---+---+---+---+---+---+---+---+---+
So the first value you see is the first element of your arr, the next two a[-1][2] and a[-1][1] are "garbage" values.
That's what happens on your system, but keep in mind that this relies on undefined behavior.