尝试在 Ubuntu 上的 NASM 上运行 .asm 文件时出错

Posted

技术标签:

【中文标题】尝试在 Ubuntu 上的 NASM 上运行 .asm 文件时出错【英文标题】:Error when trying to run .asm file on NASM on Ubuntu 【发布时间】:2011-05-14 05:26:06 【问题描述】:

我正在使用 ubuntu 64 位并尝试在 NASM 上运行 .asm 文件。但是当我尝试运行以下代码时它会返回此错误。我试图做的是通过从源代码编译(或组装)目标文件来构建可执行文件 $ nasm -f elf hello.asm,然后在创建文件后,hello.o 通过调用链接器从目标文件生成可执行文件本身

$ ld -s -o hello hello.o

这将最终构建 hello 可执行文件。

我正在关注这个教程http://www.faqs.org/docs/Linux-HOWTO/Assembly-HOWTO.html

错误:

输入文件 `hello.o' 的 i386 架构与 i386:x86-64 输出不兼容

代码:

     section .data              ;section declaration

 msg     db      "Hello, world!",0xa    ;our dear string
 len     equ     $ - msg                 ;length of our dear string

 section .text              ;section declaration

             ;we must export the entry point to the ELF linker or
     global _start       ;loader. They conventionally recognize _start as their
             ;entry point. Use ld -e foo to override the default.

 _start:

 ;write our string to stdout

         mov     edx,len ;third argument: message length
         mov     ecx,msg ;second argument: pointer to message to write
         mov     ebx,1   ;first argument: file handle (stdout)
         mov     eax,4   ;system call number (sys_write)
         int     0x80   ;call kernel

  ;and exit

     mov    ebx,0   ;first syscall argument: exit code
         mov     eax,1   ;system call number (sys_exit)
         int     0x80   ;call kernel

【问题讨论】:

【参考方案1】:

如何在 Ubuntu 64 位上编译、链接和运行 nasm 应用程序。

安装 nasm:

sudo apt-get install nasm

用文件名hello.asm保存文件:

section .data
  hello:     db 'Hello world!',10    ; 'Hello world!' plus a linefeed character
  helloLen:  equ $-hello             ; Length of the 'Hello world!' string
                                     ; (I'll explain soon)

section .text
  global _start

_start:
  mov eax,4            ; The system call for write (sys_write)
  mov ebx,1            ; File descriptor 1 - standard output
  mov ecx,hello        ; Put the offset of hello in ecx
  mov edx,helloLen     ; helloLen is a constant, so we don't need to say
                       ;  mov edx,[helloLen] to get it's actual value
  int 80h              ; Call the kernel

  mov eax,1            ; The system call for exit (sys_exit)
  mov ebx,0            ; Exit with return code of 0 (no error)
  int 80h

编译:

nasm -f elf64 hello.asm

链接:

ld -s -o hello hello.o

运行它

el@apollo:~$ ./hello
Hello world!

有效!现在怎么办? 请求您最喜欢的编译器生成汇编代码,它通常会被传递以转换为机器代码。谷歌搜索:“将php/java/python/c++程序转换为程序集”

观点:当今所有人都在试图为公众拆除并摆脱通用计算,因此我们必须教新学生如何构建通用计算的概念图灵机从核心原理,到裸机,最后是汇编程序和编程语言。

学习汇编对编程有何帮助? 99% 的计算机程序比优化后的速度要慢 10 到 100 倍,这仅仅是因为程序员不知道他们最喜欢的高级编译器或解释器对他们施加了哪些延迟。

全面了解此处的完整堆栈意味着您可以强制您的程序拥有令人垂涎的特性,即只需几纳秒即可完成手头的工作。时间==金钱。因此,了解如何避免任何需要超过几纳秒才能完成的事情可以节省时间,从而节省金钱。

https://softwareengineering.stackexchange.com/questions/156722/how-does-learning-assembly-aid-in-programming

【讨论】:

谢谢,我使用 Sasm 作为 ide,它在链接器上有 -m64 之类的选项,还有 -g 这给我带来了麻烦......顺便说一句,答案很干净......跨度> 【参考方案2】:

您需要告诉链接器生成 i386 输出文件,因为您正在编写 i386 程序集:

ld -m elf_i386 -s -o hello hello.o

【讨论】:

当我使用这个命令时,它返回同样的错误:ld: i386:x86-64 architecture of input file `hello.o' is incompatible with i386 output @psyhclo:不,那是不是同样的错误,那是相反的错误,因为你也告诉nasm创建x86-64输出。做一个另一个,而不是两个! (我强烈建议创建i386 输出,这意味着像您最初那样调用nasm,并以这种方式调用ld,因为您实际上是在编写i386 汇编程序而不是x86-64)。【参考方案3】:

这看起来可能是nasm 产生的内容与ld 试图制作的内容之间的简单不匹配:

i386 architecture of input file 'hello.o' is incompatible with i386:x86-64 output

换句话说,nasm 已经生成了一个 32 位目标文件 hello.o 并且 ld 想要使用它并生成一个 64 位可执行文件。

nasm -hf 命令应该为您提供可用的输出格式:

valid output formats for -f are (`*' denotes default):
  * bin       flat-form binary files (e.g. DOS .COM, .SYS)
    ith       Intel hex
    srec      Motorola S-records
    aout      Linux a.out object files
    aoutb     NetBSD/FreeBSD a.out object files
    coff      COFF (i386) object files (e.g. DJGPP for DOS)
    elf32     ELF32 (i386) object files (e.g. Linux)
    elf       ELF (short name for ELF32) 
    elf64     ELF64 (x86_64) object files (e.g. Linux)
    as86      Linux as86 (bin86 version 0.3) object files
    obj       MS-DOS 16-bit/32-bit OMF object files
    win32     Microsoft Win32 (i386) object files
    win64     Microsoft Win64 (x86-64) object files
    rdf       Relocatable Dynamic Object File Format v2.0
    ieee      IEEE-695 (LADsoft variant) object file format
    macho32   NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (i386) object files
    macho     MACHO (short name for MACHO32)
    macho64   NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files
    dbg       Trace of all info passed to output stage

我看到您的链接教程要求您运行:

nasm -f elf hello.asm

尝试使用:

nasm -f elf64 hello.asm

相反,您可能会发现ld 不再抱怨输入文件。

【讨论】:

这不是真正正确的方法,因为 OP 正在编写的程序集也必须修改(例如,%rax%rbx 等的高 32 位需要在系统调用之前被清除)。 是的,@caf,你可能是对的。我自己,我更喜欢更改代码方法,因为我正在运行 64 位,但我可以看到在某些情况下创建 32 位可执行文件会更好。您的答案可能提供了让这些东西正常工作的最小努力版本,因此这可能是学习教程的最佳方式。所以+1。 我按照@paxdiablo 说的做了,效果很好。那么这是正确的做法吗?因为对我来说工作得很好!谢谢。 谢谢,我使用 Sasm 作为 ide,它在链接器上有 -m64 之类的选项,还有 -g 这给我带来了麻烦......顺便说一句,答案很干净......跨度>

以上是关于尝试在 Ubuntu 上的 NASM 上运行 .asm 文件时出错的主要内容,如果未能解决你的问题,请参考以下文章

我正在尝试运行 CUDA 示例,但我在 Ubuntu 16.04 LTS 上遇到了 openGL (libGLEW.a) 问题

错误记录Ubuntu 编译 ffmpeg 报错 ( nasm/yasm not found or too old. Use --disable-x86asm for a crippled bu )

使用 nasm 和 qemu 运行引导加载程序的问题

在ubuntu 10.10安装好了nasm 可是我想编译一段代码却总是错误?

NASM汇编学习系列——获取命令行参数

NASM汇编学习系列——示例打印0到10