我目前正在尝试用Rust(Windows 32-bits)写一个程序,基本上可以从它自己的.text部分提取一些特定的部分机代码。
基本上,如果我定义并调用了一个函数 test1
作为。
unsafe fn test1(){
asm!("
pushad
.byte 0x90, 0x90, 0x09, 0xC0, 0x09, 0xDB, 0x09, 0xC9, 0x90
inc eax
mov eax, ebx
xor eax, eax
.byte 0x90, 0x09, 0xC0, 0x09, 0xDB, 0x09, 0xC9, 0x90, 0x90
popad
"
:
:
:
:"intel");
}
它将输出。
inc eax
mov eax, ebx
xor eax, eax
该程序使用 .byte 0x90, 0x09, 0xC0, 0x09, 0xDB, 0x09, 0xC9, 0x90, 0x90
和 .byte 0x90, 0x09, 0xC0, 0x09, 0xDB, 0x09, 0xC9, 0x90, 0x90
来识别要检索的代码(这些操作码代表了一些重要的信息)。nop
和 or reg, reg
基本上什么都不做)。)
一切都很好,直到我试着做以下事情。
unsafe fn test2(){
asm!("
.byte 0x90, 0x90, 0x09, 0xC0, 0x09, 0xDB, 0x09, 0xC9, 0x90
"
:
:
:
:"intel");
while a < 10{
a += 1;
}
asm!("
inc eax
dec eax
.byte 0x90, 0x09, 0xC0, 0x09, 0xDB, 0x09, 0xC9, 0x90, 0x90
"
:
:
:
:"intel");
}
它只检测到... inc/dec
指令,这意味着我看不出有什么东西可以在内联汇编的两种用法之间成为Rust代码的汇编等价物(while循环递增的 a).
我真的不知道Rust编译器是如何处理内联汇编的,但我逻辑上认为它应该尊重代码的执行顺序......
我希望我的问题足够清楚。
在优化的输出中,除了中间执行的程序集会有相同的可观察效果外,基本上没有任何保证。这意味着不能保证排序或汇编看起来和输入一样。众所周知,编译器会将某些计算系列的循环转换为其等价的和函数)。
如果你想在优化后的汇编中找到与一段代码相关的汇编,把这段代码放在它自己的函数中,并把这个函数和它调用的所有函数标记为no_inline。并确保你想看到的所有代码都有可观察的效果,或者使用benchmark::black_box来假装它有。