As always reference the LinuxCNC manuals and the LinuxCNC Wiki for more information.
The first thing we want to look at is how to call a subroutine and pass some variables to the subroutine. This could be for making multiple parts or having multiple fixtures or being able to spell out the location of the part.
Lets examine the subroutine it self, it starts with the sub tag and ends with the endsub tag. When a subroutine is called all of the code between the two tags will be executed unless you sneak in a return in the sub.
o123 sub (some useful code here) o123 endsub
o<myname> sub (some useful code here) o<myname> endsub
Notice that when you use a name you must surround it with < > and when you use numbers you do not use the < > characters. Named subroutines are easier to figure out what it might do from the name so using names is the preferred way.
|A subroutine in the same file as it is called in must be before the call.|
o<circle> sub (msg, some useful code here) o<circle> endsub o<circle> call M2
Notice in the above G code file the subroutine is before the call line. Looks pretty useless so far but wait there’s more…
o<circle> sub G0 X[#1] Y[#2] (debug, X = #1 and Y = #2) (msg, some useful code here) o<circle> endsub o<circle> call [1.5] [2.0] M2
OK, now were getting some meat and potatoes. A couple of new things showed up on the second line there is the Chinese stuff with the symbols and a debug and some more things on the call line.
Subroutines are passed 30 variables starting with #1 and ending with #30. They are passed in order so the first one goes to #1 etc. The  around the #1 mean to evaluate what is between the . For example if you did X[#1 + 2] then 2 will be added to the value passed to parameter #1 and X will be equal the sum of both values.
Debug is a special comment and it will evaluate any variables and print the values of the variables. If you create a program and run the above G code in the Axis simulator you will see how it works.
o<circle> sub F25 (getting the radius from the diameter value) (that was passed by dividing it in 1/2) (then storing it in a named parameter) #<radius> = [#3 / 2] G0 X[#1 - #<radius>] Y[#2] (debug, X = #1 Y = #2 radius = #<radius>) G2 X[#1 - #<radius>] Y[#2] I[#<radius>] J0 (msg, some useful code here) o<circle> endsub (X center, Y center, Circle Diameter) o<circle> call [1.5] [2.0]  G0 X0 Y0 M2