x86 子指令操作码混淆 [英] x86 sub instruction opcode confusion

查看:33
本文介绍了x86 子指令操作码混淆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用 Turbo Assembler 和 Turbo Debugger 时,我对操作码感到惊讶.更准确地说,我有一些组装好的二进制文件,Turbo Debugger 在其中反汇编了这个词

Playing around a bit with Turbo Assembler and Turbo Debugger, I was surprised about opcodes. More precisely, I have some assembled binary in which Turbo Debugger disassembles the word

29 C3

正确地sub bx, ax.但是,Turbo Assembler 将完全相同的指令 sub bx, ax 组装到以下字

correctly to sub bx, ax. However, Turbo Assembler assembles the very same instruction sub bx, ax to the following word

2B D8

对此感到困惑,我发现 this 引用说明寄存器的减法从寄存器中可能确实以 292B 开头.完全相同的指令可以用不同的操作码表示吗?如果是这样,那是为什么?是因为历史原因和兼容性吗?引用说明了操作码的不同操作数类型,它们只是在 sub bx, ax 中重合.这是为了以后通过自修改代码或类似方式修补不同操作数的能力吗?此外,Turbo Assembler 是否有语法结构来选择一个操作码而不是另一个?

Being puzzled about that, I found this reference stating that subtraction of a register from a register may indeed begin with both 29 and 2B. Is it indeed the case that exactly the same instruction can be expressed by different opcodes? If so, why is that? Is it for historical reasons and compatibility? The reference states different operand types for the opcodes, they just coincide for sub bx, ax. Is this for the ability to later patch in different operands via self-modifying code or the like? Furthermore, does Turbo Assembler have a syntax construct to choose one opcode over the other?

注意:我知道像 jejz 这样的条件跳转具有相同的操作码,因为它们具有相同的标志相关行为和不同的助记符是为了反映同一操作的不同语义,但前者让我感到困惑.

Note: I was aware of conditional jumps like je and jz having the same opcode as they have the same flag-dependent behaviour and the different mnemonics are there to reflect different semantics of the same operation, but the former confuses me.

推荐答案

大多数 x86 指令支持两个操作数,其中一个操作数可以是内存操作数.这是通过在 modr/m 字节中编码操作数来支持的.这个字节总是编码一个寄存器操作数和一个寄存器或内存 (r/m) 操作数,但指令必须决定它的操作数中哪个是寄存器操作数,哪个是内存操作数.

Most x86 instructions support two operands of which one operand can be a memory operand. This is supported by encoding the operands in a modr/m byte. This byte always encodes one register operand and one register or memory (r/m) operand, but the instruction must decide which of its operands is the register operand and which is the memory operand.

因此,为了支持在源操作数或目标操作数中包含内存操作数,许多指令都可以使用一种变体,其中源操作数可以是内存操作数,另一种变体可以是目标操作数.这通常由位 01 控制(在某些手册中称为 d 位).

So to support having the memory operand in the source or the destination operand, many instructions are available with one variant where the source operand can be a memory operand and one variant where the destination can be a memory operand. This is generally controlled by bit 01 (dubbed the d bit in some manuals).

因此,不需要内存操作数的指令可以采用两种方式进行编码,而汇编器通常会选择一种或另一种作为有点随机的实现细节.

As a consequence, instructions that do not need a memory operand can be encoded both ways and assemblers generally pick one or the other as a somewhat random implementation detail.

这篇关于x86 子指令操作码混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆