【问题标题】:GAS Assembly program segmentation fault (writing to auto variable)GAS 汇编程序分段错误(写入自动变量)
【发布时间】:2017-08-24 09:02:17
【问题描述】:

我打算在 C 中这样做:

#include<stdio.h>
int main() {
  int arr[5];
  arr[0] = 5;
  arr[1] = 0;
  arr[2] = 1;
  arr[3] = 3;
  arr[4] = 4;
  int max = 0;
  for(int i = 0;i < 5;i++)
    if(max < arr[i])
      max = arr[i];
  printf("%d\n", max);
  return 0;
}

这是我的代码链接:array_max.s。这是我的 AT&T 格式的汇编代码:

.data

.text
.globl _start
_start:
  movl $5, -20(%ebp)
  movl $0, -16(%ebp)
  movl $1, -12(%ebp)
  movl $3, -8(%ebp)
  movl $4, -4(%ebp)
  movl $0, %ecx
  movl $5, %eax
  loop:
    cmp $0, %eax
    je terminate
    cmp %ecx, -20(%ebp,%eax,4)
    jg assign
    jmp loop


terminate:
  movl $4, %eax
  movl $1, %ebx
  movl $1, %edx
  int $0x80
  movl $1, %eax
  int $0x80
  ret

assign:
  movl -20(%ebp,%eax,4), %ecx
  ret

我在第一条指令movl $5, -20(%ebp) 上遇到了分段错误。我是新手,请帮忙。

【问题讨论】:

  • _start被调用时,%ebp指向什么?你从来没有设置你的堆栈框架。
  • 不是专家但不应该将%ebp 初始化为一些有效的内存?在堆栈中保留内存并写入?
  • @Jean-FrançoisFabre 不,不是。在组装中不会发生任何魔法,只有您设置/保留/获取的东西可用。
  • 我想系统会为您提供一些寄存器中的参数。否则,我同意其余的,只是我不是 x86 专家......
  • @Ped7g:OP 确实指定了 32 位 Linux 并且正在使用 int 0x80 系统调用 ABI,因此很明显这段代码针对的是 x86-32 System V psABI。在_start%esp = 堆栈中,带有 argc、argv[] 内容和堆栈上的 envp。大多数其他寄存器 = 垃圾(或在 Linux 中 = 0)。 @Abhishek:调试器应该告诉你%ebp=0。

标签: c linux assembly x86


【解决方案1】:

我在第一条指令movl $5, -20(%ebp) 上出现分段错误。

您没有在堆栈上为arr 分配任何空间(即:int arr[5]):

pushl %ebp
movl %esp, %ebp
subl $20,%esp //<--- memory allocation

为了通过恢复前一个堆栈帧来释放分配在堆栈上的内存,请在 ret 之前使用 leave 指令。

【讨论】:

  • 嘿,在我的终止标签中,我试图在终端上打印存储在%ecx 中的值。但它没有打印任何东西。你能帮忙打印%ecx中的值吗?
  • @AbhishekAgrawal 在执行cmp $0, %eax 时,寄存器eax 始终为5。因此,永远不会执行比较之后的条件跳转,也永远不会到达标签terminate
  • 是的,这是我的新代码,可以正常工作,但不能打印。链接:collabedit.com/yc4x8.
  • @AbhishekAgrawal ecx 必须包含您要打印的地址。在int $0x80 之前执行push %ecxmovl %esp, %ecx
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多