I understand that the ret imm16 (C2 imm16) instruction with an operand of zero is no different than the operandless ret (C3) in its effect. However, when I explicitly give my assembler ret 0, should it not encode that as the ret imm16 instruction since I explicitly provided the operand?
If I assemble the following code with the version of ml.exe that ships with VS2019 with the command ml file.asm /link /SUBSYSTEM:CONSOLE /ENTRY:stdMain
.386
.MODEL FLAT, STDCALL
.CODE
stdMain PROC
xor eax, eax
ret 0
stdMain ENDP
END
Then open the executable with a disassembler, I see the instruction that was encoded for ret was C3:
00401000: 33 C0 xor eax,eax
00401002: C3 ret
I can manually enforce the C2 instruction by hard coding the bytes for it:
.386
.MODEL FLAT, STDCALL
.CODE
stdMain PROC
xor eax, eax
db 0c2h, 0, 0 ; ret imm16=0
stdMain ENDP
END
Now I see the C2 instruction in the disassembled output:
00401000: 33 C0 xor eax,eax
00401002: C2 00 00 ret 0
Is it correct for an assembler to 'optimize' like that?