assembly - 32 位寄存器中非零字符的高效 UTF-8 字符长度解码

标签 assembly utf-8 nasm x86-64 micro-optimization

我在 eax 中存储了一个 UTF-8 字符后来,在处理中,我需要知道有多少字节组成了字符。

我已经缩小了范围,最大限度地减少了变化和掩码,想知道我是否在某处错过了一些巧妙的技巧?

选项 1:蛮力

    mov     r11, 4      ;   Maximum bytes
    bt      eax, 31     ;   Test 4th MSB
    jc      .exit 
    dec     r11         ;   Lets try 3
    bt      eax, 23     ;   Test 3rd MSB
    jc      .exit 
    dec     r11         ;   Lets try 2
    bt      eax, 15     ;   Test 2nd MSB
    jc      .exit 
    dec     r11         ;   It's straight up ascii (1 byte)
.exit:

注:
  • 我在eax中积累了正如每个人所指出的那样注册错误。
  • Margaret 和 Ped7g 都提供了解决方案,我学到的比预期的还要多。
  • 最佳答案

    如果您可以假设 correct encoding of the character ,您可以简单地检查第一个代码单元中最高零的位置(感谢 UTF-8 的自动同步属性)。

    罪魁祸首是对于一个代码单元的代码点,最高零是第 7 位。对于 n 个代码单元的代码点,最高位是 7 - n(注意“不连续性”)。

    假设第一个代码单元在 al .

    not al                 ;Trasform highest 0 in highest 1
    bsr al, al             ;Find the index (from bit0) of the first 1 from the left
    xor al, 7              ;Perform 7 - index
                           ;This gives 0 for single code unit code points
    mov ah, 1
    cmovz al, ah           ;Change back to 1
    

    请注意 bsr没有为 0 的输入定义,但这只会发生在无效的前导代码单元(值为 11111111b)。

    您可以使用 jz <error handler> 检测无效的 0xff 代码单元后 bsr操作说明。

    感谢@CodyGray 指出原始版本的错误。
    感谢@PeterCorders 指出执行 7 - AL 的 XOR 技巧。

    关于assembly - 32 位寄存器中非零字符的高效 UTF-8 字符长度解码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41264555/

    相关文章:

    assembly - 为什么 AT&T 程序集中需要使用 '$' 标志?

    git - 包含混合编码文件的现有 Git 存储库

    java - 使用 java -jar 运行代码时如何打印 UTF8

    assembly - DOSBox - 该程序无法在 dos 模式下运行(汇编)

    segmentation-fault - 处理 SIGCHLD NASM

    linux - 64 位 Linux 上的 SDL 和 nasm

    c - asm()的 "long form"是什么?

    c++ - 了解如何手动发出处理器指令

    assembly - 用 MASM 汇编语言定义带参数的函数

    将 =C3=B6 转换为 ö 假设 UTF-8