You were doing good... until:
mov a, eax
mov b, ebx
As you noted when you pushed 'em, the unadorned names "a" and "b" are the address of "a" and "b". What you're attempting is essentially moving eax to the number 5 - not the contents of the memory address [5]! Obviously not possible...
mov [a], eax
mov [b], ebx
... would be "legal", but not what you want to do. Your variables are actually two bytes long, the '3' and the linefeed. Moving the (four byte) address into one would clobber the other. What you want to do (if I understand it) is to move one byte of the "[contents]" from one variable to the other.... ( this would be "dereferencing" the variable that you've passed by "reference", I believe)
mov cl, [eax] ; cl - one byte - has '3'
mov ch, [ebx] ; ch - one byte - has '7'
mov [ebx], cl
mov [eax], ch
We could also employ the "xchg" instruction:
mov cl, [eax]
xchg [ebx], cl
mov [eax], cl
As I understand it, "xchg" with [memory] implies "lock". Probably faster to do it the naive way(?).
See if that gets you past the "sticking point". If not, we can discuss it further...
Best,
Frank