为什么nasm在寄存器之间组装MOV指令时使用0x89?

1 assembly nasm

为什么NA​​SM在两个寄存器之间组装MOV指令时使用0x89操作码(137)?

以下是使用NASM汇编的代码示例:

55      push ebp
89E5    mov ebp, esp
83EC04  sub esp, byte +0x4
31C0    xor eax, eax
C9      leave
C3      ret
Run Code Online (Sandbox Code Playgroud)

我想要这样的东西:

55      push ebp
8BEC    mov ebp, esp
83EC04  sub esp, byte +0x4
33C0    xor eax, eax
C9      leave
C3      ret
Run Code Online (Sandbox Code Playgroud)

我想要0x8B的原因是:如果你查看MOV指令的二进制表示,它在NASM中看起来像这样:

Opcode   Mod Reg R/M
10001001 11  100 101 (89 E5)
Run Code Online (Sandbox Code Playgroud)

令人困惑的部分是reg操作数是第二个.

NASM的语法是这样的:0x89 11 source_reg destination_reg
MOV指令是mov destination_reg, source_reg

phu*_*clv 6

两个操作码是相同的.这是x86的冗余.汇编程序可以选择它喜欢的任何东西

A typical instruction of x86 architecture has two opcodes. The first of them has a register as the first operand and a register or a memory location as the second one (that's abbreviated "reg, reg/mem32" in the opcode reference or "Gv, Ev" in the opcode table). The operands for the second opcode are reversed (that's abbreviated "reg/mem32, reg" or "Ev, Gv"). This makes sense: the processor must know if it copies to the memory, or from the memory. But when both operands are registers, the encoding becomes redundant:

                  ; mod reg r/m
03C3 add eax, ebx ;  11 000 011
01D8 add eax, ebx ;  11 011 000
Run Code Online (Sandbox Code Playgroud)

There are much more than just reg/reg style like this. See it here

Different assemblers emit different opcodes, so this technique can be used to identify the assembler

Some assemblers allow you to choose the encoding. For example GAS can emit the other encoding if you affix .s to the end

10 de   adcb   %bl,%dh
12 f3   adcb.s %bl,%dh
Run Code Online (Sandbox Code Playgroud)

What is the ".s" suffix in x86 instructions?