I'm not sure where you got the idea to use dynamic arrays in what is obviously a beginner's programming task, because the complications of having to handle memory allocations and zero-based array indexes are a bit of a distraction from the task you're at.
One of the main reason Delphi implements dynamic arrays is to handle the situation where the number of elements isn't know until run-time (another is to allow the writing of routines that aren't tied to a specific number of array elements). However, in your case, you don't need the complications of using dynamic arrays, they just introduce possibilities for avoidable errors.
In a traditional version of an exercise like this, one would use static arrays:
var
RegNo: array[1..100] of string; // assuming you actually want 100 elements
Speed: array[1..100] of real;
The advantages of doing it that way include
The arrays can have intuitive lower and upper bounds, not 0 and 98: Of course, that's assuming you really did intend to have 99 elements in your arrays, not 100, and that illustrates the sort of mistake it's easy to make if you use dynamic arrays, or zero-based arrays generally when they're not a natural fit to your programming task.
If the arrays are global variables (not local variables of a procedure or function) you can just use the arrays without further ado, i.e. no need to do memory allocation (SetLength) on them before you use them and no need to release the memory afterwards. The reason for that is that at run-time, global variables are automatically filled with zeroes as the program starts, so the program starts with them in a known state.
I agree with David Heffernan's comment that having range checking on can help pick up out-of-range array indexes, but in something as simple as this, it's probably best not to rely on "training wheels" and instead get used to getting your array indexes correct in the first place. Having to mentally jump back and forth between your mental model of the array and the array bounds and indexing of a zero-based array is probably one of the most frequent sources of error. And unless someone has deliberately made life difficult for you by insisting on zero-bases arrays, use the luxury of natural array bounds that Pascal permits to make life easier on yourself.
Local variables are allocated on the stack (and with certain exceptions, managed-lifetime variables which are a bit of an advanced topic) and therefore contain random values, so they should be initialized before use, by doing something like:
FillChar(MyArray, SizeOf(MyArray), Chr(0));
Some may disagree, but imo, it's better to get in the habit of initializing variables even when you don't need to (like global variables), rather than trip over an uninitialized one.
It's worth mentioning that the bounds of an array don't need to be overtly numeric. For example, given an enumeration
type
TFruit = (apple, pear, banana);
you can then declare an array
var
Calories : array[apple..banana] of real;
This is a style you often see in Pascal tutorials which predate Delphi and is mainly thanks to its objective as a strongly-typed, teaching language.