linux - printf 和退出表单 C 的 x86 assembly 错误

标签 linux assembly x86-64 cpu-architecture

我在汇编代码方面遇到了一些问题。我正在尝试调用 C 函数打印。 我编译文件:

gcc helloC.s -o hello

我得到了这样的错误:

 /tmp/cc0SwfB8.o: In function `_start':
(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crt1.o:(.text+0x0): first defined here
/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status

这是我们教授给的程序。我在大学电脑上用腻子编译。 Linux函数:lscpu说是x86_64架构。

我们教授给出的代码:

#PURPOSE: This program writes the message "hello world" and
# exits
#
.section .data
helloworld:
.ascii "hello world\n\0"
.section .text
.globl _start
_start:
main:
pushq $helloworld
call printf
pushq $0

call exit

由于 64 位架构,我在此代码中唯一更改的是 push -> pushq。

编辑: 正如 fuz 所说,我将 .globl _start 更改为 .globl main。 Olso 我将标签 _start: 更改为 main: 我编译没有错误。

当我在午餐程序中使用 ./hello 时,它会说:“违反内存保护”(从我的母语翻译而来。(Naruszenie ochrony pamięci))

#PURPOSE: This program writes the message "hello world" and
# exits
#
.section .data
helloworld:
.ascii "hello world\n\0"
.section .text
.globl main
main:
pushq $helloworld
call printf
pushq $0

call exit

最佳答案

您不能像那样机械地将 x86 汇编代码转换为 x64 汇编代码。

选择:

  • 为 x86 编译并运行。
  • 学习调用约定并重写
  • 用C重写

您违反内存保护的原因是您使用任意参数调用 printf。 printf 的第一个参数进入 x64 中的 rdi 寄存器,而不是堆栈。

关于linux - printf 和退出表单 C 的 x86 assembly 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49819589/

相关文章:

C 内联 ASM : passing integers to a register

c - 在 ‘%xmm1’ 中修复未知的寄存器名称 ‘asm’ ?

assembly - "Hello, World"在 FreeBSD 11.2 上使用 nasm

linux - 尝试安装 DOCKER GPG key 时收到错误 : Curl: option '-' is unknown

linux - 在 makefile 中使用 grep 命令?

linux - 杀死命令中特定值位于特定范围之间的进程

assembly - ARM 的加载和存储字节和半字指令如何工作?签名与未签名有何作用?

assembly - Lazarus FPC 拒绝 ASM 中 AND op 的 64 位值

macos - 无法将 .data 中的变量移动到 Mac x86 程序集的寄存器

mysql - Raspbian - 尝试安装 mysql-server 时出现 dpkg 错误