The culprit has to do with opening forms and dynamically paging through them, I think. I'll show you a fairly simple test. I'm going to suggest that you run the Windows Performance Monitor that is (usually) found under Start >> Programs >> Accessories >> System Tools. The later your version of Windows, the more options you will have on the monitor control panel. You want to look at this and identify where the memory-related numbers are shown. If you can add memory factors to the real-time graph, better still!
Start the Perf monitor. Minimize the window but do not close it.
Start your Access code. Trigger your process that steps through the form's recordsource using DoCmd. Now immediately maximize the window with the perf monitor and see what resource is dropping to zero. 'cause this is almost surely a resource issue.
Don't tell me to use update query - I can't do that
Sure you can; you just don't want to or perhaps THINK you can't. But you really can. You just haven't told us what else is going on behind the form.
There is another way to skin this cat (MMMMEEEEEEOOOOOWWWWW!

) that does not involve paging through forms. Which is, I think, the source of your problem.
Windows garbage collection (memory reclamation, in this case) is not very good. I am betting that one of two things is happening. Either (A) you are consuming virtual space such that your swap file gets consumed, or (B) you are fragmenting system memory (one of the scratchpad pools, Gates alone knows which one). The Win Perf Mon will possibly find out which one for you. If you see one of the resources in the Perf Mon display drop to zero, that's your problem. No questions, no doubts.
So how do you do this without an update query?
If you can open a form in VBA, you can just as easily use VBA to open a recordset to whatever it is that drives the form (form's recordsource). Find the table or query that is the source of the form's fields. Directly open the implied recordsource rather than the form.
Now in your recordset loop, do an Edit on the recordset, copy field A to field B, do an Update on the recordset, and loop until you are done that way.
If your problem is that the form is driven from an implied query (i.e. when you open the form's recordsource in design mode you see an SQL statement, not a query or table name), cut/paste the query and make it a "real" query. Then open THAT as the recordset.
If the reason you can't do this in an update query is because of something
else the form does for you when you do a "Forms_OnCurrent" event or some other event like "AfterUpdate", duplicate that code in the loop via cut/paste if no other way exists to do that. What you want to avoid is getting the graphics interface involved because of something called "system resources."
I think if you set aside the fixation on the form and perhaps just do this through a recordset operation, you will put far less strain & drain on memory. It will probably be a lot quicker, too!