As you rightfully note, if this routine is called with a call then [ebp+4] is the return address. That does not mean that this is a bad idea.
Assume that the routine is called with a call. At that point, the "return address" which is pushed on the stack is the address of the byte which immediately follows the call opcode. Let's call this address x. The routine then extracts from address x two 32-bit words, one at address x and one at address x+4. It subtracts the second word from the first one, storing the result in eax. Finally, the routine stores back the value x+8 in the stack slot [ebp+4], the net effect being that when the ret is reached, execution resumes at address x+8. With this hypothesis, the routine looks like a way to subtract integers which are located in the middle of the code, something like this:
call yourroutine
dd 56478634
dd 18943675
mov ebx, eax ; an example instruction
Here, the call returns to the mov instruction, and at that point eax contains the value 37534959 (that's 18943675 subtracted from 56478634).
As a code routine, it is not terribly useful, since it is a convoluted way to load eax with a constant value which is hardcoded (code space is normally read-only during execution). One might imagine that such a routine could appear as part of the runtime support for dynamic linkage on some architecture (dynamic linkage is a hairy subject).
Now, let's assume, instead, that the routine is invoked with a jmp. [ebp+4] now designates whatever was on top of stack at that point. The routine takes that value (let's call it y), get the two words at addresses y and y+4, computes the subtraction result into eax, and then stores y+8 back into the [ebp+4] slot. Finally, the ret interprets that slot as a return address, i.e. the address of some code to which execution should jump. It does not matter that no call opcode was involved in the production of that address; ret will jump to it nonetheless. This time, the invocation code may look like:
push foobar
jmp yourroutine
... ; unreached code
foobar:
dd 56478634
dd 18943675
mov ebx, eax ; an example instruction
This time, this looks like a parameterized jump with some inherent loading of eax. Code like that can exist in the implementation of some interpreters for threaded code. As a homework question, however, I am quite sure that this was not what was intended (threaded code interpreters are even hairier than dynamic linking).