The pusha/popa register save-and-restore sequence you're simulating here is exactly what xv6's swtch.S and every real x86 kernel's context switch does to move the CPU from one task's stack to another's. Forgetting to save ESP separately (pusha doesn't cover it) is a classic bug that corrupts a task's entire stack the moment it resumes, wiping out every local variable it had in flight.