7

I see code like:

mov ax, cs
mov ds, ax
mov es, ax

Why can't I just compress this to:

mov ds, cs
mov es, cs

Is the first way faster since its using the accumulator register? But that wouldn't seem intuitive since cs and ds are segment registers. Or is there some restriction that I'm unaware of?

I'm using nasm by the way.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
samoz
  • 56,849
  • 55
  • 141
  • 195

4 Answers4

11

You can't mov segment register to segment register -- there's no instruction for it.

Dave
  • 10,369
  • 1
  • 38
  • 35
  • When I first read your response I didn't believe you, but in NASM's documentation, sure enough, no mov reg_dseg, reg_cseg instruction. – samoz May 29 '09 at 20:57
  • This is not the reason, it is the result. –  May 29 '09 at 20:58
  • 1
    What? I don't understand what you mean Neil. – samoz May 29 '09 at 21:06
  • Ask yourself WHY the x86 does not have those particular instructions. –  May 29 '09 at 21:10
  • 4
    @Neil - Actually this *is* the answer to "Why do the book authors not mov ds, cs?" and even more specifically his question "is there some restriction that I'm unaware of?" However, the next natural question would be "wtf, why not?" so your answer is helpful there. – dss539 May 29 '09 at 21:14
2

Look at the Intel Manual Volume 2 Instruction Set Reference - 325383-056US September 2015 "MOV Move" column "Instruction".

The only 16-bit mov to registers is encoded in:

mov r/m16, Sreg

And "3.1.1.3 Instruction Column in the Opcode Summary Table" explains:

  • r/m16 — A word general-purpose register or memory operand used for instructions whose operand-size attribute is 16 bits. The word general-purpose registers are: AX, CX, DX, BX, SP, BP, SI, DI.
  • Sreg — A segment register.

Thus mov ds, cs is not encodable, as there is no mov Sreg, Sreg version.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
2

There is only so much room in a processor for the microcode for all its instructions. So one general instruction is often preferred over several special purpose ones for rarely uused operations lake changing segment registers. Also, for some processors the number of instructions is absolutely limited by the architecture - for example, the original 8080 processor was limited to 256 instructions as they all had to have the op code encoded in a single byte.

  • Coding space in the machine code is also an issue for 8086. Presumably they wanted to leave room for future expansion. As well as microcode space, there's also the complexity of the decoder hardware to support decoding more different opcodes. (Unless 8086 decoding itself was done by microcode? IDK). But yes, spending an opcode for a rarely-used instruction that (when it is used) only saves 1 2-byte instruction vs. the alternative is not worth it. – Peter Cordes Mar 20 '20 at 22:50
0

It's not the assembly language really but the underlying machine language which prevents these operations.

While assembly is made up of easy to read words or mnemonics, they actually represent quite directly the 1s and 0s of the machine code. On x86 CPUs each instruction is typically made up of a sequence of bytes with individual bytes or even bits within the bytes having meaning. Certain bits represent the instruction, others represent the addressing mode. In register addressing modes such as your examples some bits represent which specific registers are to be used as the source and destination of the mov instruction.

Now the x86 family of processors go back a long way to the 1970s when CPU architecture was simpler. In those days the concept of the accumulator was of key importance - ax is the 16-bit x86 accumulator. All calculations were built up or "accumulated" in this register so it was available to all instructions. Other general purpose registers had a more restricted range of use.

Because instructions were based on bytes you wanted as few bytes to represent an instruction as possible to keep instruction decoding fast. To keep as many instructions as short as possible the use of the accumulator is made central.

On more modern CPUs such as the Motorola 680x0 more general purpose registers have more abilities that were previously the domain of the accumulator. On RISC CPUs all registers are as flexible as accumulators. I have heard that in 64-bit mode the current x86/amd64 instruction set is now much less restricted.

hippietrail
  • 15,848
  • 18
  • 99
  • 158
  • Not until x86_64 that registers can be used like that. Since 32-bit x86 most registers can act more or less as a general purpose register – phuclv Mar 17 '14 at 01:20
  • It looks like I was unaware the question was about segment registers as well as the accumulator. I never got into x86 assembly because of the horrible way memory worked but then with segment registers and stuff. I believe it's much nicer to work in now that there is a nice flat memory model. – hippietrail Mar 17 '14 at 02:17
  • I don't go much though x86 assembly too. But there are still segment instructions on x86 too. x86's address space is not flat – phuclv Mar 17 '14 at 02:27
  • 1
    It's more complicated than that. There are various modes that have been added over the generations, and the various operating systems did not always use the most powerful available mode at the time. x86 CPUs have tons of stuff left in for backward compatibility. These days on modern OSes you don't need to worry about segments. This is what I mean by "flat memory model". I don't know how much the segment registers are used these days, or whether they are necessary, or whether they are just general purpose registers now that retain their old names ... – hippietrail Mar 17 '14 at 02:39
  • @LưuVĩnhPhúc: You've inspired me to ask a new question: [Do the x86 segment registers have special meaning/usage on modern CPUs and OSes?](http://stackoverflow.com/questions/22446104) – hippietrail Mar 17 '14 at 02:48
  • 1
    Your first paragraph is solid, but the rest is sketchy. [`mov r/m, Sreg` and `mov Sreg, r/m`](https://www.felixcloutier.com/x86/mov) can use any GP-integer register or addressing mode as the non-Sreg operand. They're not limited to AX. In general, even 8086 could do stuff like `add bx, cx` with the same opcode it would use for `add ax, cx`, just a different destination in the ModRM byte encoding the operands. x86 is not an accumulator machine. AX was special for some operations on 8086, but not most basic ALU stuff. (Unlike on 8080 where `A` was much more special). 386 made AX less special – Peter Cordes Mar 20 '20 at 22:56