在下列程序集中:
mov dx, word ptr [ebp+arg_0]
mov [ebp+var_8], dx考虑到这是一个集合的C函数,有多少位宽(C函数的参数) arg_0?(局部变量C变量) var_8有多少位宽?也就是说,它是短的,int的,等等。
由此看来,var_8是16位,因为dx是16位寄存器.但我对arg_0不太确定。
如果程序集还包含此行,则:
ecx, [ebp+arg_0]这是否意味着arg_0是一个32位的值?
发布于 2018-05-08 09:57:29
为了解决这个问题,有三个原则需要理解。
如果存储的大小为32位(请注意后缀mov [var], 1 ),则模糊指令movl $1, var是AT&T语法中的movl $1, var,因此很容易判断直接操作数的大小。
接受Intel语法的汇编程序需要一种推断此大小的方法,有四种广泛使用的选项:
例如,当涉及到寄存器时,
- _It is inferred from the other operand._就是这种情况。
mov [var], dx是一个16位的商店。-明文规定。
mov WORD [var], dx
MASM-语法汇编程序在大小之后需要一个PTR,因为它们的大小说明符只允许在内存操作数上使用,而不是直接或其他任何地方。
这是我喜欢的形式,因为它是明确的,它是突出的,它是不容易出错的(mov WORD [var], edx是无效的)。-从上下文中推断。
var db 0 mov var,1;仅MASM/TASM。将尺寸与标签相关联
MASM-语法汇编程序可以推断,由于var是用db声明的,所以它的大小是8位,存储也是这样(默认情况下)。
这是我不喜欢的形式,因为它使代码更难阅读(组装的一个好处是指令语义的“局部性”),并将高级别的概念(如类型和存储大小等低级别概念混合在一起)。这就是为什么NASM的语法不支持魔法/非本地大小关联。。-在大多数情况下,只有一个正确的尺寸
push、分支和所有指令都是这样,它们的操作数大小取决于内存模型或代码大小。
对于某些指令,可以重写实际使用的大小,但默认情况是一个明智的选择。(例如push 123)
简而言之,汇编程序必须有一种方法来判断其大小,否则它将拒绝代码。(或者一些低质量的汇编程序(如emu8086 )对于模棱两可的情况有一个默认的操作数大小。)
如果您正在查看反汇编代码,反汇编程序通常采取安全的一面,并始终明确说明大小。
如果没有,您必须求助于手动检查操作码,如果反汇编程序不会显示操作码,则是时候更改操作码了。
反汇编程序不难找到操作数的大小,因为它正在反汇编的二进制代码是由CPU执行的,指令操作码是操作数大小的代码。
尝试从反汇编中推断变量的类型并非徒劳无功,但我们也必须考虑到平台,而不仅仅是体系结构。
讨论了这里使用的主要模型。
数据类型LP64 ILP64 LLP64 ILP32 LP32 char 8 8 8短16 16 16 _int32 32 int 32 64 32 32 16 64 32 32 32长64 64指针64 64 64 32 32
x86_64上的窗口使用LLP64。x86-64上的其他OSes通常使用x86-64系统V,这是一个LP64模型。
在链接类型为long long (64位)的long long变量为1的ORed变量时,clang只在低字节下使用ORing的REX前缀。如果变量立即用两个dword加载或一个qword重新加载,则会导致存储转发失速,因此这可能不是一个好的选择,特别是在32位模式下,or dword [bar], 1大小相同,并且很可能作为两个32位二分之一重新加载。
如果你不小心地看分解的代码,他们就可以推断出bar是8位的。
这种技巧,其中一个变量或一个对象,被部分访问是常见的。
为了正确猜测变量的大小,需要一些专门知识。
例如,结构成员通常是填充的,因此在它们之间存在未使用的空间,这可能会使没有经验的用户认为每个成员都比它大。
堆栈具有精确的对齐要求,这也是可能会扩大参数的大小的要求。
经验法则是编译器通常倾向于保持堆栈16字节对齐,并且自然地对齐所有变量。多个窄变量被打包到一个dword中。。当通过堆栈传递函数args时,每个函数都被填充到32位或64位,但这并不适用于堆栈上局部变量的布局。
最终回答你的问题
是的,在第一个代码片段中,您可以假设arg_0的值是16位宽。
注意,由于它是传递到堆栈上的函数arg,所以它实际上是32位,但是上面的16位没有被使用。
如果代码中出现的mov ecx, [ebp+arg_0]比您对arg_0值大小的猜测要晚得多,那么它肯定至少是32位。
它不太可能是64位(64位类型在32位代码中是罕见的,我们可以做这个赌注),所以我们可以得出它是32位。
显然,第一个片段是那些只使用变量的一部分的技巧之一。
这就是如何处理反求工程--一个变量的大小--进行猜测,验证它是否与代码的其余部分一致,如果不是,则重新访问它,重复。
随着时间的推移,你会做出更好的猜测,根本不需要修改。
https://stackoverflow.com/questions/50223972
复制相似问题