It is written:
If you think of an eval STRING as a call back from the interpreter to the compiler, then you might think of a BEGIN as a call forward from the compiler into the interpreter. Both temporarily put the current activity on hold and switch modes of operation.
Pretty self-explanatory.
print "start main running here\n";
eval "BEGIN{print qq(BEGIN: before eval compilation at run-time
+\n)} END{print qq(END: from eval STRING\n)}";
eval {BEGIN{print qq(BEGIN: before eval compilation at compile-t
+ime\n)} END{print qq(END: from eval BLOCK\n)}};
END { print "END: done running\n" }
BEGIN { print "BEGIN: still compiling\n" }