push $3 is a 64-bit push. How many bytes does the push instruction push onto the stack when I don't specify the operand size?
But that doesn't even matter because you moved RSP to point 12 bytes below the saved RBP value (which RBP points at) before doing the first push.
At process startup in a static executable run by Linux, i.e. at _start the way you apparently built your program, all the registers (except RSP) are zeroed, and stack memory below the initial RSP starts out zeroed. This is not officially guaranteed by the ABI but is in practice how Linux works. That's why you loaded zeros.
mov -4(%rbp), %rax loads 8 bytes. The low 4 bytes of that load comes from space you skipped with sub $12, %rsp. The high 4 bytes are from the bottom of the saved RBP value. Both of those things are 0 because Linux zeroed them while initializing a fresh process.
The value you load from memory into RAX was never going to be a pointer so it makes no sense as an arg to GDB's x command. x eXamines memory at a given address. What would make sense is x /16gx $rsp to dump 16 qwords above RSP.
Also note that sub $12, %rsp looks like it was naively ported from 32-bit code. That misaligns the stack. At _start, it was already aligned by 16. _start is not a function; nothing called it and you can't ret from it. You don't need to save the old RBP, or even do anything with RBP at all; one pointer to the stack (RSP) is generally enough.
At the top of a function that does get called, RSP-8 would be 16-byte aligned, so one push would re-align the stack.