尝试执行二进制文件时“没有此类文件或目录”错误

时间:2015-12-12 16:24:25

标签: linux assembly ubuntu-14.04 nasm x86-64

我在Ubuntu上使用NASM汇编程序。我正在尝试执行此代码:

section .data

fmt db "%d",0
val1 dd 23
val2 dd 9
val3 dd 7

section .text
global _start
extern printf

_start:
push val1
push val2
push val3

pop rax 
pop rbx 
imul rax, rbx
push rax 

pop rax 
pop rbx 
add rax, rbx
push rax

pop rax 
mov [val1], rax

push val1
push fmt
call printf
add rsp, 16

mov rax,0   
ret 

nasm -f elf64 test64.asm成功创建了test64.o并且ld -s -o hello test64.o -lc创建了一个可执行文件,但是当我尝试运行它时,我得到一个“没有这样的文件或目录”错误。

2 个答案:

答案 0 :(得分:2)

1)您使用printf的错误调用约定。参数在寄存器中传递,而不是在堆栈中传递:https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI。此外,printf需要EAX中的值(在您的情况下为0)。

2)程序启动时,堆栈上没有返回地址。看这里:http://www.dreamincode.net/forums/topic/285550-nasm-linux-getting-command-line-parameters。为此,

mov rax,0   
ret 

错了。但是如果你使用64-bit-Linux-syscall

mov edi, 0                  ; return 0 (success)
mov eax, 60                 ; sys_exit
syscall

您将看不到printf的输出,因为它被缓冲并且不会刷新缓冲区。您可以致电fflush(0)exit

3)要在Linux中使用C函数,您必须使用特殊加载器(/lib64/ld-linux-x86-64.so.2)进行链接。我只是不知道它是否默认安装。

4)push val1推送val1的地址,而不是其值。使用括号来获取值。我想你只想将32位DWORD加载到64位寄存器中。您可以直接将DWORD加载到32位寄存器(64位寄存器的上半部分将被清除)或使用movsx进行签名操作。

精髓:

section .data

fmt db `%d\n`,0             ; backticks for '\n'
val1 dd 23
val2 dd 9
val3 dd 7

section .text
global _start
extern printf, exit

_start:

movsx rax, dword [val1]     ; signed dword to signed qword
movsx rbx, dword [val2]
imul rax, rbx

mov ebx, [val3]             ; unsigned dword into RBX
add rax, rbx
mov [val1], rax

mov rdi, fmt                ; string pointer
mov rsi, [val1]             ; immediate value
xor eax, eax                ; no vector registers used
call printf

xor edi, edi
call exit
  

nasm -f elf64 test64.asm
    ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o test64 test64.o -lc
    ./test64

答案 1 :(得分:0)

  1. 您是否尝试过启动它?

    ./test
    
  2. 可能是,当前路径不在路径列表中,在哪里搜索可执行文件。

    1. 检查权限是否允许执行文件,例如:

      $ ls ./test
      
      -rwxr-xr-x user user .... test