What is the purpose of XORing a register with itself?
eax零集xor eax, eax永远,好吗?操作系统开发的时候,为什么不把它放进我的+ +可执行的代码。这是更有效的,mov eax, 0吗?
1 2 3 4 5 6
| 012B1002 in al,dx
012B1003 push ecx
int i = 5;
012B1004 mov dword ptr [i],5
return 0;
012B100B xor eax,eax |
另外,in al, dx均对它的是什么?
- MSVC++编译器实际上不太可能发出"in"指令。您可能在错误的地址/错误的对齐方式下进行分解。
- 我只是在调试模式下使用反汇编程序。
- 是的,真正的指令会提前几个字节开始。没有"in"指令的C等价物,从16位I/O端口读取并重写结果(稍后几条指令是非常不可能生成的指令序列)。
- 一个非常类似的问题:stackoverflow.com/questions/1135679/…
- 过去和最近出现的一个有趣的提示和技巧文档是来自MS Winword 1.1源(computerhistory.org/_static/atchm/…)的"86fun.doc"。该文件位于"opusetalcashmeredoc"中,描述了汇编程序编程的"最佳/快速实践",还提到了XORBX、BX实践。
- 这个问题有多个重复项:stackoverflow.com/questions/33666617/…(它有一个详细的答案,有一些微架构背景)和stackoverflow.com/questions/1135679/…。此外,stackoverflow.com/questions/17981447/…解决了微体系结构的原因(并将snb的xor at reg rename与ivb的mov elimination(at reg rename)进行了比较)。
型
是的,效率更高。
操作码比mov eax, 0短,只有2个字节,处理器识别出特殊情况,将其作为mov eax, 0处理,不存在对eax的错误读依赖,因此执行时间相同。
- "处理器重新划分特殊情况,将其视为"mov eax,0",而不存在对eax的错误读取依赖,因此执行时间是相同的"处理器实际上做得更好:它只在内部执行寄存器重命名,甚至对eax根本不做任何操作。
- 事实上,从整体上看,它更快。必须从RAM中提取的字节更少。
- 通过执行xor eax, eax防止生成空字节操作码;)
- @枪手在写炮弹代码101:)
- 在现代体系结构中,XOR将更快,因为在重命名阶段寄存器设置为零,而不使用任何执行单元stackoverflow.com/a/18027854/995714
型
另外,为了避免在编译时使用0,如用于利用shell代码的缓冲区溢出等,为什么要避免0?0表示C/C++中字符串的结尾,如果剥削的平均值是字符串处理函数等,则shell代码将被截断。
顺便问一下,我指的是最初的问题:"有什么理由做一个"xor eax,eax"?不是MSVC++编译器所做的。
由于评论中有一些关于这在现实世界中是如何相关的争论,请参阅这篇文章和维基百科的这一部分。
- 我觉得这听起来像胡说八道。您的代码中一定有零字节,所以我不知道再多一个字节会有什么不同。不管怎样,谁在乎你是否能欺骗一个程序把代码当作数据来读取。真正的问题是将数据作为代码执行。
- 谁在乎?黑客是这样做的,显然大部分与计算机安全相关的行业。在投票否决某件事之前,请先自学。你可以在这里找到更多的参考文献[The Art of Exploration-Chapter 0x2a0][1]以及不包含0的示例shell代码[1][books.google.es/…
- 这使人们想起了TRS-80。我们中的一些人会在基本字符串中嵌入汇编例程。在源代码中,有几个字符在不破坏源代码的情况下是绝对无法显示的,因此必须仔细优化任何此类例程,以避免使用这些字符。
- 我不知道为什么这会被否决很多次,wtf。投反对票的人,请在投反对票之前在Shellcodes中自学这项最基本的技术/知识。
- @kizzx2可能是因为这里没有人解释过在.text段中如何解析字符串。我也看不出终止一个字符串是如何允许某人移动.data段以镜像.text段来修改任何内容的。请比"最基础的技术"更具体一些。
- @Hawken Kripop_Ash曾提到,它正在回答"执行XOR的任何原因"部分,避免使用空值是一个有效的原因。现在,人们可以对它"偏离主题"的原因投反对票,但似乎没有人说得很清楚,感觉就像人们投反对票,因为他们认为在安全上下文中空字节根本不重要,所以我咆哮道。
- @不过,根据我在shell code上的发现,避免空字节对于编写shell代码而不阻止代码被利用非常重要。您能解释一下指令段中的空字节是如何使所述代码更容易被利用的吗?
- @霍肯"顺便问一句,我指的是最初的问题:"有什么理由做一个"xor eax,eax"?不是MSVC++编译器所做的。"
- @Kizzx2你能解释一下在你的程序指令段中有空字节是如何使它更容易被利用的吗?空字节只影响字符串解析,据我所知,没有任何东西可以解析程序的指令段。请解释,不要引用与使用MSVC++无关的内容
- @霍肯·阿法克,这不是通常的情况,但在我看来,这是一个战略武器。这个答案增加了编译器可能希望避免空字节的另一个原因,不一定是最"合乎逻辑"的答案。在这里,有人可能会说,答案将MSVC描绘成一种工具,使开发人员更容易编写shell代码。
型
xor eax, eax是将eax设置为零的更快方法。这是因为你返回零。
in指令正在处理I/O端口。基本上是从指定的端口dx中读取一个字的数据,并将其存储在al中。不清楚为什么会发生在这里。这里有一个参考资料,似乎可以详细解释。
- "in指令正在处理IO端口的事务"。但在本例中,它可能是一个"工件",由调试器在指令中间开始反汇编而引起。
- 我同意。不过,这就是它的作用。
- @亚伯,你为什么重命名所有的助记键和注册名?至少可以说,这是不合常规的。正如您在OP代码中看到的,大多数现代汇编程序和反汇编程序都使用小写拼写。
- @康拉德,我接受纠正。我的ASM书籍,包括英特尔的处理器参考(全部都超过5年),(编辑:显然是维基百科),只使用大写字母,没有意识到这个惯例被改变了。
- @如果我记得正确,在AT&T语法中也不允许使用大写的abelmar
- 答案是可编辑的。
型
使用XOR reg, reg或XORPS reg, reg的另一个原因是打破依赖链,这使得CPU能够更有效地优化汇编命令的并行执行(甚至它增加了一些更多的指令吞吐量预先确定)。
- 这使它比AND reg, 0有优势,但不比MOV reg, 0有优势。DEP断链是xor的一种特殊情况,但一直是mov的情况。这并没有被提到,这导致了人们偶尔的困惑,他们认为mov错误地依赖于被覆盖的旧值。但当然不是。
- 任何关于这个的推荐,我都不知道我头上戴着破坏者的名单。
- 覆盖目的地而不依赖它的所有内容都会破坏DEP链。例如,每3个操作数的op dest, src1, src2指令(例如VPSHUFB dest, src1, src2或lea eax, [rbx + 2*rdx]都会破坏dest旧值上的dep链。只有当存在对旧值的错误依赖时才值得注意:像mov ax, bx,它(在amd/silvermont/p4上,而不是p6/snb)对eax的旧值有错误的DEP,即使你从未读过eax。在英特尔,最值得注意的一点是,popcnt/lzcnt/tzcnt的输出有错误的DEP。
- 当然,mov ax, bx / mov [mem], eax与eax以前的值有依赖关系,但这不是错误的依赖关系。你实际上在使用这些比特,所以这是一个真正的依赖。
型
XOR操作确实非常快。如果结果是将寄存器设置为零,编译器通常会以它所知道的最快的方式执行。像xor这样的位操作可能只需要一个CPU周期,而一个拷贝(从一个寄存器到另一个寄存器)只需要很少的时间。
在不同的目标CPU体系结构下,编译器编写者通常甚至会有不同的行为。
型
从操作>执行"xor eax,eax"的任何原因返回0;012B100B异或EAX,EAXret<--op不显示这个
XOREAX,EAX只是0的EAX寄存器,它的执行速度比mov eax,$0,不需要取0的即时数据加载到eax中。
很明显,这是MSVC正在优化的"返回0"eax是用于从MSVC中的函数返回值的寄存器。
- 此答案不会添加其他答案中没有的任何内容。是的,所有x86 ABI都使用eax/rax作为返回值的寄存器。此外,除了作为指令解码的先决条件外,不必提取即时数据。XOR比MOV短,甚至在它所在的UOP缓存行中留下了更多的空闲空间,但是这些效果都没有被很好地描述为"不必获取"。
型
例如,XOR通常用于加密代码
1 2 3 4 5 6
| mov eax,[ecx+ValueHere]
xor eax,[ecx+ValueHere]
mov [ebx+ValueHere],esi
xor esi,[esp+ValueHere]
pop edi
mov [ebx+ValueHere],esi |
xor指令使用逻辑异或记住或使用inclusive或更好地理解xor连接两个值,请考虑这两个二进制值:
号
如果您或他们,结果是1100011011,当两个位在彼此之上相等时,得到的位是0。否则,结果位为1。可以使用calc.exe计算xor。