【问题标题】:Segmentation Fault in Assembly装配中的分段错误
【发布时间】:2012-11-17 01:13:30
【问题描述】:

我有这个汇编代码:

00000000 <Q2>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 20                sub    $0x20,%esp
   6:   c7 45 fc 1f 00 00 00    movl   $0x1f,-0x4(%ebp)
   d:   c7 45 f8 06 f4 ff ff    movl   $0xfffff406,-0x8(%ebp)
  14:   8b 45 fc                mov    -0x4(%ebp),%eax
  17:   8b 55 08                mov    0x8(%ebp),%edx
  1a:   8d 04 02                lea    (%edx,%eax,1),%eax
  1d:   89 45 f4                mov    %eax,-0xc(%ebp)
  20:   8b 45 08                mov    0x8(%ebp),%eax
  23:   0f af 45 f4             imul   -0xc(%ebp),%eax
  27:   89 45 f0                mov    %eax,-0x10(%ebp)
  2a:   8b 45 f8                mov    -0x8(%ebp),%eax
  2d:   8b 55 f0                mov    -0x10(%ebp),%edx
  30:   8d 04 02                lea    (%edx,%eax,1),%eax
  33:   89 45 ec                mov    %eax,-0x14(%ebp)
  36:   83 7d ec 00             cmpl   $0x0,-0x14(%ebp)
  3a:   74 0a                   je     46 <Q2+0x46>
  3c:   b8 00 00 00 00          mov    $0x0,%eax
  41:   8b 00                   mov    (%eax),%eax
  43:   89 45 f4                mov    %eax,-0xc(%ebp)
  46:   8b 45 f8                mov    -0x8(%ebp),%eax
  49:   89 c2                   mov    %eax,%edx
  4b:   c1 fa 1f                sar    $0x1f,%edx
  4e:   f7 7d 08                idivl  0x8(%ebp)
  51:   c9                      leave  
  52:   c3                      ret  

我认为分段错误出现在第 4e 行,在它右移十进制 0x1f (31) 后,它会除以 %edx。我认为答案很可能会导致除以0,除非该数字大于或等于2^31。

我被告知是否发生分段错误取决于函数的1个参数的值。在进一步检查汇编代码后,我得出结论,故障与参数无关。我似乎找不到我忽略的东西。有人可以帮忙吗?

【问题讨论】:

  • 第 41 行在我看来像是一个段错误。
  • @FrankKotler 如果这是目标文件的objdump 输出,则第 41 行可能有一个不可见的重定位条目。 @John 如果是这样,你可以使用-dr 开关吗?
  • 分段错误不能出现在4e 行,除非您的帧指针 (%ebp) 寄存器损坏。这是因为被零除会导致SIGFPE 与siginfo_t 具有si_code == FPE_INTDIV。你的函数中没有任何东西可以破坏%ebp,所以如果SIGSEGV出现在那行,你要么有一个非常错误的信号处理程序/自制的上下文切换器(唯一能够改变的用户空间实体%ebp),或内核错误(不太可能)。使用 'gdb' 执行 info reg / disas $eip-20 $eip+20。另外 - 您的代码是未优化的编译器输出。来源,请证明“C”标签的合理性;-)

标签: assembly x86 segmentation-fault


【解决方案1】:

问题在于这些行:

3c:   b8 00 00 00 00          mov    $0x0,%eax
41:   8b 00                   mov    (%eax),%eax

您正在将 0 移动到 %eax,然后尝试访问位于 (%eax) 的内存。在许多操作系统(例如 linux)上,尝试读取地址 0x0 将导致分段错误。

如果我正确阅读代码,除非param * (param + 31) == 3066,否则会发生这种情况,如果param 是-73 或42,就会发生这种情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多