【问题标题】:What does XLAT Instruction do in 8086?XLAT 指令在 8086 中的作用是什么?
【发布时间】:2017-11-29 15:48:58
【问题描述】:

1.XLAT有什么作用?

2。我们为什么要使用它?

【问题讨论】:

  • 即使是“x86 xlat”搜索引擎上的第一个结果也非常彻底地解释了这件事。 felixcloutier.com/x86/XLAT:XLATB.html
  • @Zahid Khan:在下面阅读我的答案
  • 表被指定为 DS:BX(BX 是表开头的内存偏移量)。 AL 是表中的索引。 XLAT 将简单地返回索引 AL 处的值
  • 举个例子。我最近写了这个SO answer,它使用 XLAT 将字节转换为 HEX 字符。特别是函数print_byte_hex。该代码用于 16 位实模式。 XLAT 用于将值 0 到 15 转换为 ASCII 值 '0 到 '9' 和 'A' 到 'F'
  • @ZahidKhan 可能(我猜,我没有投反对票)因为搜索“x86 xlat 指令”会返回许多相关资源,很难想象你不清楚什么,你会复制吗几乎没有什么问题,并解释你是如何理解它们的,或者究竟是什么,看起来你的问题付出了更多的努力。 xlat 使用的“表”是ds:(e/r)bx 指向的任意256B 内存区域,返回的字节从地址ds:(e/r)bx+al 加载。程序员可以将带有一些地址的ds:bx 设置为一些有用的数据(“表”),以将al 转换为tab[al]

标签: assembly x86 instructions


【解决方案1】:

它对 DS:BX 中指定的表进行简单的基于字节的查找(在实模式下)。例如,用于进行直接字符集转换(ASCII 到 EBCDIC)。过去我用它来进行其他基于索引/结果的字节查找。缓慢但紧凑的说明。

【讨论】:

    【解决方案2】:

    如果你懂 C,那么它的工作原理是这样的:

    const uint8_t table[256] = { ...some byte constants (table data) ... };
    const uint8_t* ds_bx = table;
    uint8_t al = <some value to translate>;
    al = ds_bx[al]; // al = table[al];
    // like "mov al,[ds:bx + al]" in ASM
    

    [ds:bx + al] 不是mov 指令的合法内存操作数,但xlat 接受它,实际上这是xlat 寻址内存的唯一方式(您不能修改它以使用不同的寄存器)。

    您将什么样的数据放入表中,或者将表放在内存中的哪个位置,取决于您。还有你用它做什么。这与内存分页或其他一些内存操作系统表无关,这只是纯粹的用户数据。

    例如,您可以使用它将菜单中的食物索引转换为食物价格,如果您的食物索引为 0..255 并且价格也适合 8 位。然后为包含价格数据的表保留 256 个字节,并用该表的地址加载ds:bx,将食物索引放入alxlat 会将索引转换为表中的价格。


    在我的Greece-flag 绘图 DOS 51B COM (binary) (source) 中,我使用 xlat 指令将条形列 0..4 的索引转换为蓝色/蓝色/白色/蓝色/蓝色配置。

    我首先检查 [x,y] 坐标是否在标志的左上角,蓝色矩形上的大白十字在哪里。如果在外面,像素的颜色是简单的(y div strip_size) &amp; 1 交替的蓝/白颜色。

    但在交叉区域内,我计算了 5x5 的网格,中间的行条是全白的。必须在[blue, blue, white, blue, blue] 中绘制中间上方和下方的两条条带,具体取决于 x 坐标(它属于哪个列条带)。为了将[0, 1, 2, 3, 4] 值转换为[1, 1, 0, 1, 1],我使用xlat 指令,指向代码本身,并屏蔽指令操作码以仅提取最低位(奇数/偶数)。通过对代码中的指令进行小的重新排列,我设法在可以通过xlat 访问它们的地址处获得所需的奇数/偶数指令操作码字节。

    如果我通过if-else 分支或其他一些算术进行转换,那么与简单的xlat 重用bxal 中已经需要的值相比,它需要更多字节的代码。


    在常见的应用程序中,您几乎找不到xlat 指令的任何用法。这是8086时代的古风,编译器肯定不会使用它,大多数手写汇编也不会,通常你可以使用简单的mov al,[bx+si]或类似的东西。

    在 32b 模式下,如果您知道该值已经零扩展至 32b,则mov al,[ebx+eax]xlat 快(结果相同)。

    在代码高尔夫中,当您尝试生成最短的机器代码时,xlat 可能会很方便(到目前为止,我一生中需要它两次,用于十六进制数字格式,以及用于希腊国旗绘图代码)。

    【讨论】:

    • 重要:ds:[bx + al]“寻址模式”它使用零扩展 AL。所以C版本肯定需要使用unsigned byte al。这显然是您想要的,但不是您从 C 中的签名数组索引中获得的。
    • 顺便说一句,如果已知 EAX 的其余部分为零,movzx eax, byte [ebx+eax] 在 32 位代码(或add cl, [ebx+eax] 或其他)中更有效(速度),但xlatb确实有用于代码大小优化的用途。在没有movzx (386) 的情况下,它可能在 8086 上最有用,因为将movzx 零扩展字节索引到完整寄存器可以解决同样的问题。
    • @PeterCordes 我永远不会期望byte 被签名...这就是为什么避免char ...我应该使用uint8_t...会编辑它。 ...哦等等,Java 已经签署了byte。 ...但 Java 是...没关系。
    • 我对@9​​87654361@ 没有任何期望,它不是标准类型。我以为你只是在编造类似 C 的术语来描述 asm。
    • xlatb 可以覆盖其段这一事实并未涵盖。所以它默认为ds:(r/e)bx + al,但可以取任何段。
    【解决方案3】:

    我已经很久没有为 8086 编程了。我记得它是用于查找表的。如果您了解 C,则可以将其与 switch() 语句进行比较,该语句在使用良好的编译器时会将所有情况转换为查找(跳转)表,而不是使用带有大量 if-then-else 的“意大利面条式编程”。

    然后每个 case 转换为跳转表中的地址 + 偏移量,然后包含要调用的函数的地址。

    然后执行一个简单的 JMP 并完成。不使用比较语句。无论您有多少案例,只需添加即可快速完成。

    【讨论】:

    • 赞成为满意,如果能够添加代码以便进一步读者更好地理解。我很乐意接受这个答案。
    • xlatb 是一个 byte 查找。 switch 跳转表绝对不是明显的用例,因为您需要将结果零扩展为 16 位。 @ZahidKhan:查找表只是一个数组。它并不意味着像switch 这样的控制流。例如为了加快popcount,您可以使用设置多少位的表,因此popcount(AL) = bits_table[AL],您可以使用xlatb 来实现。
    【解决方案4】:

    XLAT 使用 AL 寄存器的内容作为表索引,在内存中的表中定位字节条目,然后将表条目的内容复制回 AL 寄存器。

    【讨论】:

      【解决方案5】:
      TAB DB '0123456789ABCDEF'
      MOV AL,1101B ; Index = 13
      MOV BX,OFFSET TAB
      XLAT
      

      Al 的索引是 13,所以这段代码后面的 Al 将是 = 'D'

      【讨论】:

      • 那不会组装; : 是一个完整的冒号,而不是一个分号 ; 注释字符。而且您在 mov to BX 中缺少逗号。另外,1101B 不是“index = 6”,而是你在文中说的 13。
      • 感谢我编辑了代码
      • 您的答案可以通过添加有关代码的作用以及它如何帮助 OP 的更多信息来改进。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-28
      • 2016-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多