Using OR r/m32, imm32 in NASM
Asked Answered
B

1

8

The opcode generated by:

or ebx, 0ffffffffh

with NASM is:

83CBFF

But in Intel Instructions Manual:

81 /1 id      OR r/m32, imm32
83 /1 ib      OR r/m32, imm8

My question is, why NASM used the opcode 83 instead of 81, and how to generate the opcode 81?

this is the command line for NASM: nasm -fwin32 file.asm -l list.lst

Biafra answered 12/6, 2017 at 17:1 Comment(9)
why use imm32 when you can use imm8 and save a few bytes?Mm
@LưuVĩnhPhúc e.g. to align a loop.Liberia
You can write or eax, strict dword 0ffffffffh to force a 32-bit operand. But this causes NASM to use the 0D opcode (or eax, imm32) instead of 81. Of course, you can always just output the needed bytes with db.Jolee
@Jolee thank's, I've changed eax to ebx to avoid the special case of OR EAX, imm32Biafra
how about ALIGN macro?Wellspring
I think ALIGN just causes NASM to emit a series of NOPs, @Ped7g, which is less efficient than a longer form of the same instruction. Might work in other assemblers, though. MASM is a bit smarter in how it adds padding.Enrica
@CodyGray: In NASM, you can %use smartalign then ALIGNMODE p6, 32. YASM has a much nicer default, using long NOPs in a way that's optimal for Intel P6 and SnB uarches. (Probably controlled by a CPU directive or something, I forget). GNU as's .p2align also uses long NOPs by default. NASM is the exception, with nasty behaviour that will break the uop-cache by default. (More than 18 uops in a 32-byte chunk means that the code has to run from the decoders every time).Athematic
Yup, that's exactly what I was remembering about NASM's default behavior being quite undesirable. YASM, Gas, and MASM all do the right thing without any extra work required. I'd forgotten about smartalign, though, probably because I've never actually used it and it didn't get cemented in long-term memory.Enrica
@Ped7g: No current assemblers know how to stretch instructions before an ALIGN directive, unfortunately. So you always get NOPs, instead of making the same instructions take more space "for free".Athematic
J
10

NASM picks the 8-bit sign-extended immediate encoding as an optimization, because it does the same thing (-1 is representable in 8-bit 2's complement) and takes less space. You can force NASM to use a specific encoding with:

or ebx, strict dword 0ffffffffh

This results in:

81 cb ff ff ff ff

Assembling the original code without optimizations (nasm -O0) will also give this result.

Note that if the register is EAX, doing this will result in the 0D opcode (or eax, imm32) instead of 81. So in that case you might have to output the instruction yourself: db 0x81, 0xc8, 0xff, 0xff, 0xff, 0xff.

Jolee answered 12/6, 2017 at 17:29 Comment(4)
I wonder how it does the same thing, does it apply the byte operand to the all bytes of the dword?Prescribe
The imm8 is sign extended.Keystone
@SedatKapanoglu "In the forms with an 8-bit immediate second operand and a longer first operand, the second operand is considered to be signed, and is sign-extended to the length of the first operand. In these cases, the BYTE qualifier is necessary to force NASM to generate this form of the instruction."Mm
awesome. so it wouldn't be the same effect for 01h.Prescribe

© 2022 - 2024 — McMap. All rights reserved.