Linux Asm x86 производит Segfault - PullRequest
0 голосов
/ 16 декабря 2010

Я изучаю немного ассемблера для linux, и у меня есть этот пример программы, которая просто должна вызвать системный вызов write и напечатать на экране «Hello, World!», Однако она выдает ошибку. Я учусь в свободное время, а не на домашнем задании, я больше не хожу в школу!

Кто-нибудь может увидеть что-то не так с этим кодом?

xor eax,eax
xor ebx,ebx
xor ecx,ecx
xor edx,edx
jmp short string
code:
pop     ecx
mov     bl,1
mov     dl,13
mov     al,4
int     0x80
dec     bl
mov     al,1
int     0x80
string:
call code
db      'Hello, World!'

Ответы [ 3 ]

2 голосов
/ 16 декабря 2010

У меня работает. Вот что я сделал (заметьте, я на 64-битном компьютере, поэтому у меня есть дополнительный флаг для создания 32-битного бинарного файла):

test.asm

_start:
xor eax,eax
xor ebx,ebx
xor ecx,ecx
xor edx,edx
jmp short string
code:
pop     ecx
mov     bl,1
mov     dl,13
mov     al,4
int     0x80
dec     bl
mov     al,1
int     0x80
string:
call code
db      'Hello, World!'

команды:

$ nasm -felf test.asm -o test.o
$ gcc -m32 -nostdlib -nostdinc test.o -o test

, который выдал предупреждение, но это нормально.

/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.1/../../../../x86_64-pc-linux-gnu/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000008048080

Тогда я побежал:

$ ./test

и это действительно вывод "Hello, World!" (без перевода строки). Никаких ошибок.

1 голос
/ 16 декабря 2010

Я не очень знаком с ассемблером linux, но вот предположение:

При вызове API вы должны использовать специальное соглашение о вызовах.Одной из вещей, которые определены соглашением, является список регистров, которые сохраняются через вызов API.В вашем случае ошибка использует dec bl вместо xor ebx, ebx.Поскольку bl используется в качестве входного параметра, маловероятно, что он будет сохранен.То же самое для mov al, 1, безопаснее написать mov eax, 1

И я согласен с @Greg Hewgil, ваш способ получения адреса строки довольно необычен.Обычный способ записи позиционно-независимого кода со строками таков:

...
call my_print
db 'hello world!', 0
...

my_print:
pop ecx
xor edx, edx
lp:
cmp byte [ecx + edx], 0
inc edx
jne lp
lea eax, [ecx + edx] 
push eax // return address
dec edx
mov eax, 4
int 0x80
ret
0 голосов
/ 16 декабря 2010

Этот код может привести к сбою при компиляции и запуске под 64-битным ядром.64-битный обратный адрес не будет вписываться в 32-битный регистр ecx, вместо этого вам придется использовать команду rcx.Кроме того, этот код использует 32-битный API, который может быть недоступен для 64-битного ядра.Вместо этого вы должны использовать 64-битный API, как описано в моем блоге: сборка x86-64 в Linux .

...