8086 XLAT替代品

lin*_*x91 1 x86 assembly masm x86-16

XLATMASM中不起作用.

我可以使用什么来获得相同的行为:

XLAT :将AL设置为存储器字节DS:[(E)BX + unsigned AL]

Pet*_*des 6

xlatb是16,32和64位模式下的有效指令.也许你需要使用xlatbMASM 的助记符?英特尔手册表明,xlatb当与隐式操作数一起使用时,它是正确的助记符,或者xlat byte ptr [bx]用于显式形式(其中,movs操作数基本上只是文档或段覆盖,并且暗示操作数大小.)另一个想法是看看你的语法是什么反汇编程序用于指令.


但是,使用其他东西通常是一个好主意,因为它只是现代CPU上的代码大小而不是速度的胜利(例如,在Intel Haswell上3 uops).通常有更好的替代方案(特别是32或64位代码),比如使用movzx将零扩展值放入可用作索引的寄存器中.

在普通代码中,您可以:

; table in rbx
movzx  eax,  src                 ; or any other way of producing a zero-extended result in rax
movzx  eax, byte ptr [rbx + rax]     ; a movzx load avoids false deps and partial-reg slowdowns
Run Code Online (Sandbox Code Playgroud)

在8086代码中,您可以执行以下操作:

; pointer to the table in DI or SI
xor  bx,bx             ; can be hoisted out of a loop, if bh will stay zeroed

mov  bl, src   ; src can be any addressing mode, or the result of a computation

mov  bl, [si + bx]     ; this is the same load that xlat does, your choice of dest
Run Code Online (Sandbox Code Playgroud)

bx是唯一可用于16位寻址模式的寄存器,具有可单独使用的低半部分和高半部分(bl/bh).您需要一个REX前缀(仅限64位模式)才能使用sil/ dil.如果你想保持表指针bx,就像xlatb那样,你必须使用不同的寄存器进行零扩展,然后mov使用si或di.

如果表是静态的,你当然可以使用不绑定寄存器,只需使用[table + (e/r)bx].

  • 我不知道提问者是否标记了这个8086,因为他实际上是*编写代码在该处理器上运行,但是...... XLAT实际上是8086上的*巨大*性能胜利.它是一个单字节指令,并且使用缓慢的总线和有限的缓存,您可以做的任何事情来减少代码大小相当于速度的大规模,切实的改进.在一个紧密的循环中,我们谈论的是50-100个周期的差异,可能更多.通过阅读旧的优化书籍学习的琐事.当然你是对的,在现代架构上使用XLAT几乎没有任何意义(或者从386开始真正做任何事情). (3认同)
  • 只是旁注.带有内存操作数的_XLAT_并不完全用于文档(或操作数大小),它也可以覆盖段(默认为_DS_).地址本身并不重要,但是不同的段将导致添加适当的前缀(在16位和32位代码中).同样适用于`movs`指令.在这种情况下,不能覆盖目标段,但源操作数的段可以是.`xlat byte ptr es:[si]`应生成0x26 0xD7. (3认同)
  • _MLAT_或_XLATB_已经在_MASM_上作为menmonics支持了几十年,所以我冒昧地猜测OP对该指令的理解存在问题. (2认同)