Possible inaccuracy of Nasm

Programming, for all ages and all languages.
Post Reply
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

Possible inaccuracy of Nasm

Post by PeterX »

I witnessed some people using

Code: Select all

mov ds, ax
and some using

Code: Select all

mov ds, eax
which is rather confusing for me because I think only one version should work.
But when I assembled (with Nasm) and dissassembled the above instructions, they both are the same (both in real mode and in pmode)!
Isn't that an inaccuracy of Nasm?

Greetings
Peter
User avatar
iansjack
Member
Member
Posts: 4685
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Possible inaccuracy of Nasm

Post by iansjack »

When operating in 32-bit mode and moving data between a segment register and a general-purpose register, the 32-bit IA-32 processors do not require the use of the 16-bit operand-size prefix (a byte with the value 66H) with this instruction, but most assemblers will insert it if the standard form of the instruction is used (for example, MOV DS, AX). The processor will execute this instruction correctly, but it will usually require an extra clock. With most assemblers, using the instruction form MOV DS, EAX will avoid this unneeded 66H prefix.
It sounds to me as if Nasm is actually more accurate than "most assemblers".
fpissarra
Posts: 8
Joined: Mon Nov 26, 2018 9:14 am

Re: Possible inaccuracy of Nasm

Post by fpissarra »

PeterX wrote:But when I assembled (with Nasm) and dissassembled the above instructions, they both are the same (both in real mode and in pmode)!
Isn't that an inaccuracy of Nasm?
Try to compile using -O0 option (no optimization). You'll see that 'mov ds,ax' will use a 0x66 prefix on 32 or 64 bits targets.

You are right about the instruction `mov ds,eax` not existing in the official ISA from Intel, but `mov ds,rax` does. So, I think NASM allows `mov ds,eax` as an extension.

Any of these instructions will use only the lower 16 bits of GPRs.
fpissarra
Posts: 8
Joined: Mon Nov 26, 2018 9:14 am

Re: Possible inaccuracy of Nasm

Post by fpissarra »

By the way... NASM allows something like this, as well:

Code: Select all

lea eax,[5*rbx]
It'll be tranlated to `lea eax,[rbx+4*rbx]`.

This is clearly not a standard effective address calculation, but it works well on NASM.
Of course, `6*rbx` will not work.
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

Re: Possible inaccuracy of Nasm

Post by PeterX »

fpissarra wrote:Try to compile using -O0 option (no optimization). You'll see that 'mov ds,ax' will use a 0x66 prefix on 32 or 64 bits targets.

You are right about the instruction `mov ds,eax` not existing in the official ISA from Intel, but `mov ds,rax` does. So, I think NASM allows `mov ds,eax` as an extension.

Any of these instructions will use only the lower 16 bits of GPRs.
Thanks. That makes sense.

Greetings
Peter
sj95126
Member
Member
Posts: 151
Joined: Tue Aug 11, 2020 12:14 pm

Re: Possible inaccuracy of Nasm

Post by sj95126 »

fpissarra wrote:You are right about the instruction `mov ds,eax` not existing in the official ISA from Intel, but `mov ds,rax` does.
It's there, but they did a poor job of explaining it. On the page for MOV, the "mov Sreg, r/m16" syntax is marked with **, which is explained as:

"** In 32-bit mode, the assembler may insert the 16-bit operand-size prefix with this instruction"

That implies that without the operand-size prefix, the equivalent is "mov Sreg, r/m32". Normally they would put such an example in the table, and the opcodes would make it clear that "mov ds, ax" in 16-bit mode is the same opcode as "mov ds, eax" in 32-bit mode, as is the case for many 16-bit/32-bit instructions.
Octocontrabass
Member
Member
Posts: 5512
Joined: Mon Mar 25, 2013 7:01 pm

Re: Possible inaccuracy of Nasm

Post by Octocontrabass »

MOV to a segment register is always a 16-bit operation, regardless of the operand size. AMD's documentation is somewhat more clear in this regard.

The confusion in Intel's manual might be the result of trying to reconcile years of conflicting documentation without describing officially undefined behavior for MOV from a segment register. On a 386, 486, or Pentium, MOV from a segment register is always a 16-bit operation, ignoring the operand size. On a Pentium Pro or later, it ignores the operand size when the destination is memory, but obeys the operand size and zero-extends the value when the destination is a register. At some point (probably around when the Pentium was released) Intel decided to document that the upper bytes of a register destination were undefined so that software wouldn't rely on them being unchanged by the 386/486/Pentium and break when running on the Pentium Pro.
Post Reply