Call-by-value and call-by-reference are implementation techniques that were mistaken for parameter-passing modes a long time ago.
In the beginning, there was FORTRAN. FORTRAN only had call-by-reference, since subroutines had to be able to modify their parameters, and computing cycles were too expensive to allow multiple parameter-passing modes, plus not enough was known about programming when FORTRAN was first defined.
ALGOL came up with call-by-name and call-by-value. Call-by-value was for things that were not supposed to be changed (input parameters). Call-by-name was for output parameters. Call-by-name turned out to be a major crock, and ALGOL 68 dropped it.
PASCAL provided call-by-value and call-by-reference. It did not provide any way for the programmer to tell the compiler that he was passing a large object (usually an array) by reference, to avoid blowing the parameter stack, but that the object should not be changed.
PASCAL added pointers to the language design lexicon.
C provided call-by-value, and simulated call-by-reference by defining a kludge operator to return a pointer to an arbitrary object in memory.
Later languages copied C, mostly because the designers had never seen anything else. This is probably why call-by-value is so popular.
C++ added a kludge on top of the C kludge to provide call-by-reference.
Now, as a direct result of call-by-value vs. call-by-reference vs. call-by-pointer-kludge, C and C++ (programmers) have horrible headaches with const pointers and pointers to const (read-only) objects.
Ada managed to avoid this whole nightmare.
Ada does not have explicit call-by-value vs. call-by-reference. Rather, Ada has in parameters (which may be read but not written), out parameters (which MUST be written before they can be read), and in out parameters, which may be read and written in any order. The compiler decides whether a particular parameter is passed by value or by reference: it is transparent to the programmer.