gpt4 book ai didi

optimization - 英特尔前缀指令,检查优化问题

转载 作者:行者123 更新时间:2023-12-03 17:26:51 26 4
gpt4 key购买 nike

我想通过 x86_64 二进制文件和反汇编指令了解更多关于 ptrace 的功能。
目标是检查一个字节是否是指令前缀之一。

我在 Intel® 64 and IA-32 Architectures Software Developer’s Manual 中找到了一些信息(第 2 卷,第 2 章)。

专区2.1.1 INSTRUCTION PREFIXES显示以下前缀:

  • [ 0x26 ] ES 段覆盖
  • [ 0x36 ] SS 段覆盖前缀
  • [ 0x2E ] CS 段覆盖前缀或未采用分支
  • [ 0x3E ] DS 段覆盖前缀或采用的分支
  • [ 0x64 ] FS 段覆盖前缀
  • [ 0x65 ] GS 段覆盖前缀
  • [ 0x66 ] 操作数大小覆盖前缀
  • [ 0x67 ] 地址大小覆盖前缀
  • [ 0xF0 ] LOCK前缀
  • [ 0xF2 ] REPNE/REPNZ 前缀或 BND 前缀
  • [ 0xF3 ] REP 或 REPE/REPZ 前缀

  • 视觉上, this chart以黄色显示前缀。

    如果我想知道一个字节是否是前缀,我会尽量提高效率并检查是否可以执行二进制操作。

    如果我拿 0x26 , 0x36 , 0x2E0x3E作为一个团队。这些以 2 为底的数字( 00100110001101100010111000111110)显示了一个共同部分: 001XX110 .
    11100111 的与二元运算( 0xE7 ) 可以找到我的字节是否在该组中。

    伟大的。现在,如果我选择包含 0x64 的第二组, 0x65 , 0x660x67 ( 01100100 , 01100101 , 01100110 , 01100111 ),我发现了另一个常见的部分: 011001XX .

    然后, 11111100 的与二元运算( 0xFC ) 如果字节在第二组中,则可以找到。

    问题在于剩余的指令前缀( 0xF00xF20xF3 ):没有共同部分。 11111100 的与运算( 0xFC ) 会让字节 0xF1 .

    一种解决方案是检查字节是否不是 0xF1。 .

    因此,C 中可能的实现是:
    if ((byte & 0xE7) == 0x26) {
    /* This `byte` is a ES, SS, CS or DS segment override prefix */
    }
    if ((byte & 0xFC) == 0x64) {
    /* This `byte` is a FS, GS, Operand-size or address-size override prefix */
    }
    if ((byte & 0xFC) == 0xF0) {
    if (byte != 0xF1) {
    /* This `byte` is a LOCK, REPN(E/Z) or REP(_/E/Z) prefix */
    }
    }

    来自英特尔,我希望最后一组只能 checkin 一个操作。

    那么,最后一个问题是:如果字节是 0xF0、0xF2 或 0xF3,我可以 checkin 一个操作吗?

    最佳答案

    Then, the final question is: Can I check in one operation if the byte is 0xF0, 0xF2 or 0xF3?



    最接近一条指令的是:
                         ;ecx = the byte
    bt [table],ecx ;Is the byte F0, F2 or F3?
    jc .isF0F2orF3 ; yes

    但是,有时前缀不被视为前缀(例如 pause 指令,它被编码为 rep nop 以与旧 CPU 兼容)。

    另请注意,对于高速反汇编器,最快的方法可能是“跳转表驱动”,其中一个寄存器指向对应于解码器状态的表,另一个寄存器包含指令的下一个字节,例如:
                              ;ebx = address of table corresponding to the decoder's current state
    movzx eax,byte [esi] ;eax = next byte of the instruction
    inc esi ;esi = address of byte after the next byte of this instruction
    jmp [ebx+eax*4] ;Go to the code that figures out what to do

    在这种情况下,跳转到的一些代码片段会设置一些标志而不更改当前表(例如,初始表中 0xF3 的条目会导致跳转到设置“rep prefix was seen”标志的代码),并且跳转到的某些代码片段会切换到不同的表(例如,初始表中 0x0F 的条目会导致跳转到代码,该代码会更改 EBX 以指向用于所有以 a 开头的指令的完全不同的表 0x0F, ...);并且跳转到的一些代码片段会显示一条指令(并重置解码器的状态)。

    例如;对于 pause代码可能是:
    table0entryF3:
    or dword [prefixes],REP
    movzx eax,byte [esi] ;eax = next byte of the instruction
    inc esi ;esi = address of byte after the next byte
    jmp [ebx+eax*4]

    table0entry90:
    mov edx,instructionNameString_NOP
    test dword [prefixes],REP ;Was it a PAUSE or NOP?
    je doneInstruction_noOperands ; NOP, current name is right
    and dword [prefixes],~REP ; PAUSE, pretend the REP prefix wasn't there
    mov edx,instructionNameString_PAUSE ; and use the right name
    jmp doneInstruction_noOperands

    doneInstruction_noOperands:
    call displayPrefixes
    call displayInstructionName
    mov dword [prefixes],0 ;Reset prefixes
    mov ebx,table0 ;Switch current table back to the initial table
    movzx eax,byte [esi] ;eax = first byte of next instruction
    inc esi ;esi = address of byte after the next byte
    jmp [ebx+eax*4]

    关于optimization - 英特尔前缀指令,检查优化问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55764166/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com