【发布时间】:2019-09-09 20:40:54
【问题描述】:
我想通过 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、0x2E 和0x3E 作为一组。这些以 2 为底的数字(00100110、00110110、00101110 和 00111110)显示了一个共同部分:001XX110。
如果我的字节在此组中,则可以找到11100111 (0xE7) 的与二进制运算。
太好了。现在,如果我选择包含0x64、0x65、0x66 和0x67(01100100、01100101、01100110、01100111)的第二组,我发现了另一个常见部分: 011001XX.
那么,如果该字节在第二组中,则11111100(0xFC)的与-二进制运算可以找到。
问题在于剩余的指令前缀(0xF0、0xF2 和0xF3):没有公共部分。 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 */
}
}
来自英特尔,我希望最后一组只能签入一个操作。
那么,最后一个问题是:如果字节是 0xF0、0xF2 或 0xF3,我可以签入一个操作吗?
【问题讨论】:
-
你可以试着在代码高尔夫上问这个。 codegolf.stackexchange.com
-
为了让它成为话题,它需要被改写为一个谜题。
-
@prl 几乎没有办法将这个问题重写为适合 PPCG 的内容,而不会完全失去其当前的含义/请求。 PPCG 99% 的时间都是为了比赛,写一篇关于主题的非挑战真的很难。
标签: optimization x86 intel disassembly micro-optimization