If you want to create a value in memory that contains a 0 byte, you can't use it directly as an immediate operand for push or mov.  You can construct it in a register using special properties of the constant, or XOR it with something.  (Then push eax, or whatever spare register you used.)
    xor eax,eax      ; 2 bytes
    bts eax, 12      ; 4 bytes; eax |= 1<<12
    xor eax,eax      ; 2 bytes
    mov ah, 0x10     ; 2 bytes; eax = 0x10 << 8
Or push an already zeroed register and do a byte store of the non-zero byte, if you want to keep the zeroed register for later.  push eax / mov byte [esp+1], 0x10
We don't care about performance so partial-register merging isn't a problem, nor are store-forwarding stalls from a narrow store that's later reloaded with a dword load.
Constants within [-128, +127] of 0 (via push/pop) or another register (with LEA) can be constructed in 3 bytes
   push 12            ; 2 bytes, works for -128 .. +127
   pop  eax           ; 1 byte
   lea  ecx, [eax+127] ; reg+disp8 addressing mode.  ECX = 139
See also Tips for golfing in x86/x64 machine code
In general, without having special properties for the constant, you can construct it in 2 instructions with an XOR, ADD, or SUB.  (Or LEA or whatever).  XOR is easiest to see that you're not going to create any zero bytes, just pick any constant that doesn't have the same byte in the same position as the value you want.  (It doesn't have to be same in each byte, e.g. 0x12345678 also works)
   mov  eax, 0x1000 ^ 0x55555555     ;  mov eax, 0x55554555
   xor  eax, 0x55555555              ; cancel out the constant
Since we used EAX, this assembles to two 5-byte instructions:
  b8 55 45 55 55          mov    eax,0x55554555
  35 55 55 55 55          xor    eax,0x55555555
Without a spare register,
  68 55 45 55 55          push   0x55554555       # 0x1000 ^ 0x55555555
  81 34 24 55 55 55 55    xor    DWORD PTR [esp],0x55555555
Avoiding a zero in the ModRM from a [eax] addressing mode
It's not just [eax], it's using it with an AL or EAX source, or with an immediate instruction that uses /0 as extra opcode bits in the /r field.
mov r/m8, imm8 (C6 /0 ib) is one such instruction, so you can't use it with a plain [eax] addressing mode.  If you can offset the address, like inc eax / [eax-1], that works.
Use a different register for the address in the first place if you can, otherwise there are various things you can do
 c6 00 31                mov    BYTE PTR [eax],0x31   # nope, ModRM=00
 b1 31                   mov    cl,0x31               # using another register for data
 88 08                   mov    BYTE PTR [eax],cl     # /r field = 1 for the CL source
 80 20 31                and    BYTE PTR [eax],0x31   # clear bits we don't want
 80 08 31                or     BYTE PTR [eax],0x31   # set bits we do want
 # use a different register temporarily as @user200783 suggested
 91                      xchg   ecx,eax
 c6 01 31                mov    BYTE PTR [ecx],0x31
 91                      xchg   ecx,eax   # presumably need to restore it, otherwise you'd have used another reg in the first place.
  # offset the address.
 40                      inc    eax
 c6 40 ff 31             mov    BYTE PTR [eax-0x1],0x31
 # 48                      dec    eax   # optional, if you want to restore it
A couple ideas that don't work:
 # halve the address (if it's known to be aligned by 2):
 d1 e8                   shr    eax,1
 c6 04 00 31             mov    BYTE PTR [eax+eax*1],0x31   # Nope, SIB = 00
 # write more bytes: nope: mov r/m32, imm32  also has a /0 as part of the opcode
 c7 00 31 11 11 11       mov    DWORD PTR [eax],0x11111131