Выполнить strace ./my_program
- вы делаете фиктивный stat
системный вызов, затем write
, который завершается успешно, затем падает до конца и segfault.
$ strace ./foo
execve("./foo", ["./foo"], 0x7ffe6b91aa00 /* 51 vars */) = 0
stat(0x1, 0x401000) = -1 EFAULT (Bad address)
write(0, "Hello, World\n", 13Hello, World
) = 13
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0xd} ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)
Это не имена регистров, которые твоя проблема, это звонки. Вы используете 32-разрядные номера вызовов, но вызываете 64-разрядный syscall
ABI.
Номера вызовов и Соглашение о вызовах различается.
* Системные вызовы 1016 * обращают внимание только на младшие 32-битные регистры, поэтому не следует использовать их в 64-битном коде.
Код, который вы разместили в комментарии с mov rcx, message
, будет работать нормально mov ecx, message
и т. Д. , если работает с mov rcx, message
. См. Что произойдет, если вы используете 32-битный int 0x80 Linux ABI в 64-битном коде? .
Обратите внимание, что запись нулевого 32-битного регистра расширяется до полного 64 регистр, поэтому вы всегда должны использовать mov edi, 1
вместо mov rdi, 1
. (Хотя NASM сделает эту оптимизацию для вас, чтобы сохранить размер кода; они настолько эквивалентны, что некоторые ассемблеры сделают это за вас.)