寄存器有默认值吗?

时间:2010-11-10 08:35:56

标签: assembly

我正在尝试理解一些小代码:

jg 0x00000047
dec esp
inc esi
add [ecx],eax

eax 的价值是多少?这些是程序的四个第一句话,我不知道是否有默认值,或者前面的句子是否为eax添加了一些内容。

我的操作系统是Linux,可执行文件是由gcc4.3从C源代码编译的(gcc file.c exec)

4 个答案:

答案 0 :(得分:5)

取决于平台,语言和/或调用约定。但是,在此之前的代码通常应该将EAX设置为某个值。 EAX是那些经常被修改的寄存器之一,它通常不用于保存内容。

指令看起来有点随机。特别是,“dec esp”通常是一个巨大的禁忌,因为堆栈应该始终是双字对齐的。你确定这是实际代码吗?如果我正在向右翻译,指令字节转换为“\ x7fELF”,这告诉我这只是Linux程序的头字节,而不是实际的代码字节。

答案 1 :(得分:4)

我认为你真正要问的是calling convention,它描述了程序中的子程序如何将信息传递给彼此,以及操作系统如何将信息传递给程序,以及通常不同的寄存器是什么应该是的意思。

例如,大多数C编译器使用的cdecl calling convention on the x86表示当函数返回时,返回值继续在eax寄存器上。因此,如果您有一个函数int foo(),您知道在foo执行其ret操作码后,eax将包含foo返回的int。

相比之下,PowerPC处理器(通常)具有(至少)32个寄存器,简称为r0,r1,... r31。这个芯片的The AIX calling convention表示堆栈指针在r1上运行,函数参数在r3到r11上传递,返回值在r3上返回,依此类推。

重要的是要记住,调用约定有点像程序中的函数之间或库之间的协议。它不是硬件或法律的一部分,并且通常可以在平台上使用许多不同的调用约定。这就是为什么有时你会看到像

这样的代码
struct CFoo {  void __stdcall method(); };

这是对MSVC的指令,MSVC通常喜欢使用fastcall约定,告诉它对该函数使用不同的约定。如果例如函数是在由其他使用stdcall的编译器构建的库中定义的,那么这很重要。

当我们谈论操作系统如何将信息传递给程序(或操作系统的硬件)时,我们通常将其称为ABI而不是调用约定,但这是相同的想法。因此,对于您的程序,它的编写假设操作系统会在eax上传递一些特定的信息。这种假设特别适用于操作系统,编译器,甚至可能是个别程序。

答案 2 :(得分:3)

某些指令会隐式更新寄存器,即使代码中未明确列出目标也是如此。一些例子:

  • cpuid返回eax,ebx,ecx和edx
  • 中的值
  • loop递减ecx
  • rep字符串说明更改ecx,edi和esi
  • rdmsr更改了eax和edx
  • muldiv更改了eax和edx

还有很多其他例子。

您不能仅仅通过看到代码中没有列出未更改的eax来假设。

即使您知道哪些寄存器受哪些指令的影响,您对该值的唯一保证是:

  • 在您知道更新的指示后
  • 硬件重置后立即

在任何其他时间,你永远不能对这些值做出假设。

答案 3 :(得分:2)

它似乎不是有效的代码。你确定它不是文字吗?

将其解码为32位x86会产生字符串ELF

00: 7F 45  // 0x7F E
02: 4C     // L
03: 46     // F
04: 01 01  // ?? ??

尝试将文件作为ELF文件打开,而不仅仅是二进制文件。