Debuggers (such as GDB) are pretty amazing! They allow us to jump around in execution, see values of the registers... and so on. This article goes into how the debugger actually achieves what it does.
In order to pause the point of execution, there are special purpose registers that indicate when to stop. These registers (only 4 of them) are labeled DR0-DR8. DR6/7 are both used for status and control registers.
To get the general purpose registers (RAX, RBX, RSP, flags) inline assembly can be used once execution has stopped in order to grab the data from the registers. Additionally, the ptrace API can be used in order to get this information too. The ptrace API is commonly used to alter the data.
The floating point registers are a bit more complicated. The content of the floating point registers can be dumped with the FSAVE instruction and restored with the FRSTOR instruction with some additional instructions for 64 bit.
This functionality is really important for context switching. Switching between applications with context switching allows for the one program to debug and understand the other program. The ptrace API is awesome but very complicated.