1

Agner Fog's objconv shows several instances in my source disassembly where a message appears "Note: Immediate operand could be made smaller by zero extension."

For example, it appears right above these two lines:

mov rdi,out_fname_L

mov rsi,file_mode_open_read

just before a call to fopen.

out_fname_L is defined in the .data section as:

out_fname_L: db "/opt/Output_Data/A_Output_40MB",0x00

I tried these:

movzx edi,out_fname_L
movzx edi,dword out_fname_L
movzx edi,qword out_fname_L
movzx edi,byte out_fname_L (because it's a db memory operand)

but none of them works. NASM responds with "invalid combination of opcode and operands." The memory operand is a 64-bit address.

What's my mistake?

Assembled with NASM assembler for Ubuntu 18.04.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
RTC222
  • 2,025
  • 1
  • 20
  • 53
  • 2
    What it means is use 32 bit register because that's zero extended automatically. – Jester Apr 01 '20 at 17:52
  • But edi is a 32-bit register. – RTC222 Apr 01 '20 at 17:53
  • What exactly does _"but none of them works"_ mean? – Michael Apr 01 '20 at 17:56
  • NASM: "Invalid combination of opcode and operands." – RTC222 Apr 01 '20 at 17:56
  • 3
    You can't `movzx` an immediate. Use `mov edi,out_fname_L` as I said. – Jester Apr 01 '20 at 17:58
  • @RTC222 Yes. And writing to the lower 32 bit of a register clears the upper 32 bit of that register, so the contents are zero-extended. Just write `mov edi, out_fname_L`. – fuz Apr 01 '20 at 17:58
  • So it's not movxz. I'll try that now. – RTC222 Apr 01 '20 at 17:59
  • If you read Agner Fog's optimization guide, I'm sure he mentions using `mov r32, imm32` somewhere. Or checking Intel's instruction set manual should have cleared up your misconception that movzx could possibly work, because there's no immediate encoding. – Peter Cordes Apr 01 '20 at 18:02
  • @fuz - NASM responds: "relocation R_X86_64_32 against `.data' can not be used when making a shared object; recompile with -fPIC." If I add wrt ..plt to the end of the line (mov edi,out_fname_L wrt ..plt) I get: "error: ELF format cannot produce non-PC-relative PLT references." – RTC222 Apr 01 '20 at 18:06
  • 1
    See [32-bit absolute addresses no longer allowed in x86-64 Linux?](https://stackoverflow.com/q/43367427) re: using 32-bit absolute addresses like objconv is suggesting. Note that Agner Fog asked that question, and is also the author of objconv. Probably objconv hasn't been updated to check that it's disassembling a PIE with relocations, and just sees the small immediate in the current machine code. (Or else your first executable wasn't PIE but you're trying to assemble it back into a PIE?) – Peter Cordes Apr 01 '20 at 18:09
  • @Peter Cordes - Your answer to that question is long so I'll read it now. Your explanation sounds most plausible as the NASM assembler rejects everything I've tried and everything suggested here. Fog does say that objconv is not perfect so you may be right that it hasn't been updated to reflect the change he indicated in his question. Nonetheless, it's still a wonderful tool and Agner Fog is a wonderful resource. – RTC222 Apr 01 '20 at 18:14
  • 3
    NASM doesn't reject `mov edi,out_fname_L`, you just can't link it into a PIE. That message is from `ld`. Look more carefully at your terminal. Unfortunately @fuz got mixed up with AT&T syntax and the wrong destination size, but his `gcc -no-pie` is correct. NASM for position-independent LEA is `lea rdi, [rel symbol]`. Or just `[symbol]` if you use `default rel`. – Peter Cordes Apr 01 '20 at 18:21
  • Except that lea rdi, [rel symbol] is to a 64-bit register, and doesn't solve the problem of zero extension that objconv shows. – RTC222 Apr 01 '20 at 18:25
  • @RTC222 It should fix it. The displacement is a 32 bit displacement; there aren't any addressing modes with 64 bit displacements. – fuz Apr 01 '20 at 19:06
  • I guess you mean lea rdi, [rel symbol] would fix that error message? – RTC222 Apr 01 '20 at 19:32
  • @RTC222 Correct. – fuz Apr 01 '20 at 22:27
  • I've done that, and it does work. lea rdi,[out_fname_L] instead of mov rdi,out_fname_L not only eliminates the messages from objconv, but according to Fog's instruction tables, from Skylake forward lea is faster than mov in the case of reg,mem (and maybe earlier than Skylake, I didn't look). – RTC222 Apr 01 '20 at 22:35
  • BTW, I use lea rdi,[out_fname_L] instead of lea rdi,[rel out_fname_L] because my source file begins with [default rel]. – RTC222 Apr 01 '20 at 23:18

0 Answers0