【问题标题】:AT&T Assembly Printing to console Segfault [duplicate]AT&T 组装打印到控制台 Segfault [重复]
【发布时间】:2020-11-14 14:00:32
【问题描述】:

我正在关注一个在线教程,该教程提供了用 NASM 语法编写的代码。 提供的代码是:

global _start

_start:
    sub esp, 4
    mov [esp], byte 'H'
    mov [esp+1], byte 'e'
    mov [esp+2], byte 'y'
    mov [esp+3], byte '!'
    mov eax, 4    ; sys_write system call
    mov ebx, 1    ; stdout file descriptor
    mov ecx, esp  ; pointer to bytes to write
    mov edx, 4    ; number of bytes to write
    int 0x80      ; perform system call
    mov eax, 1    ; sys_exit system call
    mov ebx, 0    ; exit status is 0
    int 0x80

我已尝试将其翻译成 AT&T 语法。我写了以下内容:

.global _start

_start:
    sub $4, %esp
    movb $'H', (%esp)
    movb $'e', 1(%esp)
    movb $'y', 2(%esp)
    movb $'!', 3(%esp)
    mov $4, %eax
    mov $1, %ebx
    mov %esp, %ecx
    mov $4, %edx
    int $0x80
    mov $1, %eax
    mov $0, %ebx
    int $0x80

但是当我编译并执行这段代码时,我得到:

./build.sh: line 35: 1159 Segmentation fault    (core dumped) ./$FILE
139

我从 NASM 到 AT&T 的翻译正确吗? 如果是这样,在能够从为堆栈分配的内存中读取/写入方面,我是否缺少一些东西? (权限等)


构建信息:

在 Arch Linux 上构建 64 位系统

build.sh 脚本:

function usage { 
    echo $'\nUsage: ./build.sh -f [filename]\n'
    echo $' -f  The filename of the source file to be compiled without the file extension.\n'
}

if [ $# -lt 1 ]; then
    echo "No input files specified!"
    usage
    exit 1
fi

while [ $# -gt 0 ]; do
    case "$1" in
        -f)
            shift
            FILE=$1
            shift
            ;;
        *)
            echo "Please use -f to specify the input file!"
            usage
            exit 1
            ;;
    esac
done

if [ ! -f $FILE.s ]; then
    echo "$FILE.s doesn't exist!"
    usage
    exit 1
fi

gcc -c $FILE.s -o $FILE.o
ld $FILE.o -o $FILE
./$FILE
echo $?

【问题讨论】:

  • 你如何组装和执行你的代码?请出示您的build.sh(无论如何,这应该是一个好的minimal reproducible example的一部分。
  • 您是否将其构建为 64 位代码,因此您仅使用低半部分截断 RSP 中的 64 位堆栈指针?只有在您已经足够了解如何构建 + 运行以及任何可能的更深层次的问题以使其正确时,才能即时移植教程。但是,如果您知道正确的构建命令,只需更改语法就可以了,这与尝试将 32 位移植到 64 位或在 Mac 或 Windows 上使用 Linux 教程或其他东西不同。
  • 无论如何,这要么是Assembling 32-bit binaries on a 64-bit system (GNU toolchain) 的副本,要么是没有构建命令不可见的其他东西,在这种情况下,由于缺少minimal reproducible example,应该关闭它。 (NASM 版本对你有用吗?如果没有,可能你在 Windows 上使用 WSL1,它不支持 32 位代码。)
  • 我对你的问题投了反对票,因为它不包含minimal reproducible example,因此不承认准确的诊断。一旦您提供请求的构建脚本,将撤回我的反对票。
  • @fuz 我已经提供了请求的 build.sh 脚本,以及关于我正在构建的系统的一些更一般的信息

标签: assembly segmentation-fault stack nasm att


【解决方案1】:

尽管int 0x80 是 32 位中断,但您将其编译为 64 位代码。 我以前编译的:

as --32 inAssembly.s &&ld -o executable -m elf_i386 a.out.

as --32 inAssembly.s 使 gnu 汇编器采用 32 位架构,发出 32 位目标文件。

ld -o executable -m elf_i386 a.out 调用链接器,将目标设置为elf_i386,并将链接文件放入executable

【讨论】:

  • 另外,gcc -m32 -nostdlib -nostartfiles program.s 也很简单。
  • 我只需要 -m32 就可以了。您使用 -nostdlib 有什么特别的原因吗?似乎有点奇怪,因为我只编译程序集而不是 c 代码。
  • @Matty2532 -nostartfiles 省略了提供_start 并调用main 的C 运行时初始化,-nostdlib 未链接到libc(C 库)中。由于您不使用任何 libc 符号,因此这没有什么区别,但如果您要使用与 libc 符号同名的任何符号,则可以。
猜你喜欢
  • 2015-08-23
  • 2020-06-05
  • 2018-12-01
  • 2020-05-17
  • 2016-07-07
  • 2016-09-21
  • 1970-01-01
  • 2019-09-20
  • 2016-12-27
相关资源
最近更新 更多