Ошибка сегментации в простом коде ASM

На мой вопрос, когда я пытался создать пример NASM под 64-разрядной версией ubuntu и выполнить его после сборки и связывания с ELF. Он возвращает сообщения об ошибках, как показано ниже, когда я выполняю

NASM -f elf64 -o firstasm.o firstasm.asm ld -o firstasm firstasm.o firstasm

Ошибка сегментации (дамп ядра)

Мой код NASM будет ниже, где я пытался выполнить простые функции write () и exit ().

section .data ;Data segment

msg db "This line is test", 0x0a 

section .text ;text segment
global _start  ;Default entry point for ELF linking

_start:

; SYSCALL : write (1,msg,14)
xor rax,rax
xor rbx,rbx
xor rcx,rcx
xor rdx,rdx
mov rax,64 ; make a syscall write 4
mov rbx,1 ; put 1 into rbx and also stdout is 1
mov rcx,msg ;put address of string in rcx
mov rdx,19 ; put length of string into rdx
int 0x80   ; call kernel to made syscall

; SYSCALL : exit(0)
xor rax,rax
xor rbx,rbx
mov rax,93 ; make a syscall exit 93
mov rbx, 0  ; store 0 argument into rbx, success to exit
int 0x80

Может ли кто-нибудь указать мне, в чем проблема с моим кодом NASM, и предложения по устранению проблемы «Ошибка сегментации (дамп ядра)». Благодарю всех, кто может помочь.


person user1884888    schedule 14.01.2014    source источник


Ответы (1)


А откуда у вас номера системного вызова? Вы их вытаскиваете из воздуха?

64-разрядный sys_exit = 60 32-разрядный sys_exit = 1

64-битная sys_write = 1 32-битная sys_write = 4

64-разрядный список системных вызовов Linux

32-разрядный список системных вызовов Linux

Таблица системных вызовов Linux для x86_64

Ссылка выше покажет, какие регистры для чего используются.

32-битный системный вызов - int 0x80 не использует 64-битные регистры, и параметры регистров другие. 64-битный системный вызов - syscall.

32-битный sys_exit:

mov     ebx, ERR_CODE
mov     eax, sys_exit  ; 1
int     80h

64-битный sys_exit:

mov     rdi, ERR_CODE
mov     rax, sys_exit  ; 60
syscall

увидеть разницу?

если вы хотите создать файл inc с именами и номерами системных вызовов для ВАШЕЙ системы (возможно, они по какой-то причине отличаются)

grep __NR /usr/include/asm/unistd_64.h | grep define | sed -e 's/\#/\%/' -e 's/__NR_/sys_/' > unistd_64.inc

конечно, измените путь к unistd_64.h для вашей системы. Это будет то же самое для 32-битной версии, но, как мне кажется, файл называется unistd_32.h.

Теперь, когда я показал вам разницу между системным вызовом exit и предоставленными ссылками, вы можете исправить свой системный вызов write, чтобы он был правильным.

person Gunner    schedule 15.01.2014
comment
Спасибо Gunner за помощь, но я обнаружил, что системный вызов не работает в 64-разрядной версии ubuntu (x86_64). Вы можете указать мне, как его использовать? - person user1884888; 15.01.2014
comment
Что значит "Не работает" ?? Покажите, как вы настраиваете параметры и используете syscall - person Gunner; 16.01.2014