Я получаю ошибку EFAULT от open после использования file_name equ "a.txt"? - PullRequest
0 голосов
/ 20 марта 2019

Я получил сообщение об ошибке при запуске программы сборки x86-64 под названием time2.asm.

Я использую Ubuntu x86-64.

после выполнения системного вызова sys_open регистр rax меняет свое значение на -14, что означает ошибку efault или «неправильный адрес».

мой код предназначен для открытия файла с именем «a.txt», проверьте, произошла ли ошибка, и если нет, закройте файл.

мой код:

section .data

file_name equ "a.txt"

section .text

global _start
_start:

 ;--------------------------------------------------------------------
 ; first step-  I open a file called a.txt.

  mov rax, 2         ; sys_open
  mov rdi, file_name
  mov rsi, 0
  mov rdx, 0644q
  syscall        

  ;right after this syscall (sys_open), rax value changes to -14.


  cmp rax,0
  jl error        ;checks for error

  mov rdi,rax
  mov rax,3       ; sys_close
  syscall
  ;----------------------------------------------------------------------------

 error: mov rax,60
 mov rdi,0
 syscall ; exit program

1 Ответ

2 голосов
/ 20 марта 2019

file_name equ "a.txt" определяет file_name только для времени сборки числовая константа 1 . Неважно, в каком разделе эта директива появляется; он не собирает байтов в вывод. equ это просто вещь, постоянная во времени сборки. Аналогично %define строковой подстановке, но оно вычисляет выражение до числа на месте. (Это имеет значение для выражения, включающего $, например msglen equ $ - msg.)

Но вам нужна ваша строка в памяти, и для передачи системного вызова указатель на C-строку (неявная длина) с нулем в конце . Интерфейс системного вызова принимает только указатели, а не значения; в противном случае он не сможет обрабатывать имена файлов длиннее 8 байт. (Или 4 байта в 32-битных системах).

Таким образом

default rel
section .rodata                  ; read-only data doesn't need to be in read-write .data

file_name: db "a.txt", 0         ; the 0 terminator is important, this is a C string.

section .text
...
    lea     rdi, [file_name]   ;or mov rsi, file_name for the inefficient way

Стандартный способ помещения статических адресов в регистры в x86-64 - это LEA, относящийся к RIP. (default rel). mov edi, symbol работает в исполняемых файлах, отличных от PIE, но в принципе никогда не имеет смысла использовать mov rdi, symbol (10-байтовый mov r64, imm64).


Сноска 1:

NASM допускает многосимвольные константы в любом контексте, где допускается числовой литерал. например mov rax, 'a.txt' в точности эквивалентно mov rax, 0x7478742e61, поэтому mov [mem], rax поместит строку в память (потому что x86 имеет младший порядок), за которым следуют 3 байта нулей.

file_name equ "a.txt" в точности эквивалентно file_name equ 0x7478742e61

...