你能想到运行时代码修改的任何合法(智能)用法(程序在运行时修改它自己的代码)吗?
现代操作系统似乎对执行此操作的程序不屑一顾,因为病毒已使用此技术来避免检测.
我能想到的是某种运行时优化,它可以通过在运行时知道某些在编译时无法知道的东西来删除或添加一些代码.
executable platform-agnostic cpu-architecture instructions self-modifying
我想了解一些装配.
汇编如下,我对该testl
行感兴趣:
000319df 8b4508 movl 0x08(%ebp), %eax
000319e2 8b4004 movl 0x04(%eax), %eax
000319e5 85c0 testl %eax, %eax
000319e7 7407 je 0x000319f0
Run Code Online (Sandbox Code Playgroud)
我想了解的那点testl
之间的%eax
和%eax
?我认为这段代码的具体内容并不重要,我只是试图用自己来理解测试 - 这种价值总是不正确吗?
这个问题在我的问题上继续(根据神秘的建议):
继续我的问题,当我使用压缩指令而不是标量指令时,使用内在函数的代码看起来非常相似:
for(int i=0; i<size; i+=16) {
y1 = _mm_load_ps(output[i]);
…
y4 = _mm_load_ps(output[i+12]);
for(k=0; k<ksize; k++){
for(l=0; l<ksize; l++){
w = _mm_set_ps1(weight[i+k+l]);
x1 = _mm_load_ps(input[i+k+l]);
y1 = _mm_add_ps(y1,_mm_mul_ps(w,x1));
…
x4 = _mm_load_ps(input[i+k+l+12]);
y4 = _mm_add_ps(y4,_mm_mul_ps(w,x4));
}
}
_mm_store_ps(&output[i],y1);
…
_mm_store_ps(&output[i+12],y4);
}
Run Code Online (Sandbox Code Playgroud)
这个内核的测量性能是每个周期大约5.6个FP操作,虽然我预计它将是标量版本性能的4倍,即每个周期4.1,6 = 6,4 FP操作.
考虑到权重因素的移动(感谢指出这一点),时间表如下:
看起来调度没有改变,尽管在操作之后有一条额外的指令movss
将标量权重值移动到XMM寄存器然后用于shufps
在整个向量中复制这个标量值.似乎权重向量已经准备好用于mulps
考虑从加载到浮点域的切换延迟,因此这不应该产生任何额外的延迟.
此内核中使用的movaps
(对齐,打包的移动)addps
和mulps
指令(使用汇编代码检查)与其标量版本具有相同的延迟和吞吐量,因此这不会产生任何额外的延迟.
有没有人知道每8个周期的额外周期花费在哪里,假设这个内核可以获得的最大性能是每个周期6.4个FP运算并且每个周期运行5.6个FP运算?
顺便说一下,这是实际装配的样子:
…
Block x:
movapsx (%rax,%rcx,4), %xmm0
movapsx 0x10(%rax,%rcx,4), %xmm1
movapsx 0x20(%rax,%rcx,4), %xmm2
movapsx 0x30(%rax,%rcx,4), %xmm3
movssl …
Run Code Online (Sandbox Code Playgroud) 我的应用程序中有一个乘法添加内核,我想提高它的性能.
我使用英特尔酷睿i7-960(3.2 GHz时钟)并已使用SSE内在函数手动实现内核,如下所示:
for(int i=0; i<iterations; i+=4) {
y1 = _mm_set_ss(output[i]);
y2 = _mm_set_ss(output[i+1]);
y3 = _mm_set_ss(output[i+2]);
y4 = _mm_set_ss(output[i+3]);
for(k=0; k<ksize; k++){
for(l=0; l<ksize; l++){
w = _mm_set_ss(weight[i+k+l]);
x1 = _mm_set_ss(input[i+k+l]);
y1 = _mm_add_ss(y1,_mm_mul_ss(w,x1));
…
x4 = _mm_set_ss(input[i+k+l+3]);
y4 = _mm_add_ss(y4,_mm_mul_ss(w,x4));
}
}
_mm_store_ss(&output[i],y1);
_mm_store_ss(&output[i+1],y2);
_mm_store_ss(&output[i+2],y3);
_mm_store_ss(&output[i+3],y4);
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用压缩的fp向量来提高性能,我已经成功完成了,但我想知道为什么单个标量代码无法满足处理器的峰值性能.
我的机器上的这个内核的性能是每个周期大约1.6个FP操作,而每个周期最大的是2个FP操作(因为FP add + FP mul可以并行执行).
如果我对研究生成的汇编代码是正确的,理想的时间表将如下所示,其中mov
指令需要3个周期,从依赖指令的加载域到FP域的切换延迟需要2个周期,FP乘以4个循环,FP添加需要3个循环.(注意,乘法 - > add的依赖性不会导致任何切换延迟,因为操作属于同一个域).
根据测量的性能(最大理论性能的约80%),每8个周期有大约3个指令的开销.
我想要:
当然,存在缓存未命中和数据错位的问题,这可能会增加移动指令的延迟,但是还有其他因素可以在这里发挥作用吗?像寄存器读取档位或什么?
我希望我的问题很明确,在此先感谢您的回复!
更新:内循环的程序集如下所示:
...
Block 21:
movssl (%rsi,%rdi,4), %xmm4
movssl (%rcx,%rdi,4), %xmm0
movssl 0x4(%rcx,%rdi,4), %xmm1 …
Run Code Online (Sandbox Code Playgroud) C#没有暴露哪些IL指令?
我指的是像sizeof和cpblk这样的指令 - 没有执行这些指令的类或命令(C#中的sizeof是在编译时计算的,而不是在运行时AFAIK计算的).
其他?
编辑:我问这个的原因(并希望这将使我的问题更有效)是因为我正在开发一个小型库,它将提供这些指令的功能.sizeof和cpblk已经实现 - 我想知道在继续之前我可能错过了什么.
编辑2:使用Eric的答案,我编写了一份说明列表:
列表中没有包含许多其他指令,我将它们分开,因为它们基本上是其他指令的快捷方式(压缩以节省时间和空间):
关于这个LEAL指令,0x10的功能是什么?它是一个乘法或加法还是别的?
leal 0x10(%ebx), %eax
Run Code Online (Sandbox Code Playgroud)
有人可以澄清一下吗?这是Linux机器上的x86汇编程序.
我喜欢这个例子,所以我在c中写了一些自修改代码...
#include <stdio.h>
#include <sys/mman.h> // linux
int main(void) {
unsigned char *c = mmap(NULL, 7, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|
MAP_ANONYMOUS, -1, 0); // get executable memory
c[0] = 0b11000111; // mov (x86_64), immediate mode, full-sized (32 bits)
c[1] = 0b11000000; // to register rax (000) which holds the return value
// according to linux x86_64 calling convention
c[6] = 0b11000011; // return
for (c[2] = 0; c[2] < 30; c[2]++) { // incr immediate data after every run
// rest of …
Run Code Online (Sandbox Code Playgroud) 我正在尝试为学术研究实现Java的一个子集.好吧,我处于最后阶段(代码生成),我编写了一个相当简单的程序来查看如何处理方法参数:
class Main {
public static void main(String[] args) {
System.out.println(args.length);
}
}
Run Code Online (Sandbox Code Playgroud)
然后我构建了它,并通过我在以下网址找到的在线反汇编程序运行'Main.class':http: //www.cs.cornell.edu/People/egs/kimera/disassembler.html
我得到了'main'方法的以下实现:(反汇编输出在Jasmin中)
.method public static main([Ljava/lang/String;)V
.limit locals 1
.limit stack 2
getstatic java/lang/System/out Ljava/io/PrintStream;
aload_0
arraylength
invokevirtual java/io/PrintStream.println(I)V
return
.end method
Run Code Online (Sandbox Code Playgroud)
我的问题是:
1.aload_0
应该将'this'推送到堆栈(这就是JVM规范似乎说的)
2.arraylength
应该返回引用位于堆栈顶部的数组的长度
所以根据我的说法,1和2的组合甚至不应该起作用.
它是如何/为什么有效?或者是反汇编工具,实际的字节码是别的吗?
我正在尝试学习汇编(所以忍受我),我在这一行得到了一个编译错误:
mov byte [t_last], [t_cur]
Run Code Online (Sandbox Code Playgroud)
错误是
error: invalid combination of opcode and operands
Run Code Online (Sandbox Code Playgroud)
我怀疑这个错误的原因只是因为一个mov指令不可能在两个内存地址之间移动,但是半小时的谷歌搜索并且我无法确认这一点 - 是这样的吗?
另外,假设我是对的,这意味着我需要使用寄存器作为复制内存的中间点:
mov cl, [t_cur]
mov [t_last], cl
Run Code Online (Sandbox Code Playgroud)
什么是推荐使用的寄存器(或者我应该使用堆栈)?
我正在开发一个应用程序,在进入应用程序的主页面之前(初始注册后)让用户通过一个简短的游览.我想做的是使用以下设计覆盖应用页面(通过标签栏看到):
然而,React Native Overlay有一段历史,它遗留了很多错误 - 它也没有为我个人工作过.React Native ToolTip模块不再受支持,也不起作用.有没有人做过这个?如果是这样,怎么样?感谢您的意见!
instructions ×10
assembly ×6
c ×3
x86 ×3
intel ×2
performance ×2
bytecode ×1
c# ×1
cpu-cache ×1
executable ×1
il ×1
ios ×1
jasmin ×1
java ×1
jvm ×1
mov ×1
overlay ×1
react-native ×1