2011-01-13 17 views
27

Próbuję użyć funkcji w złożeniu, wywoływanej z projektu C. Ta funkcja ma wywoływać funkcję libc, powiedzmy, printf(), ale nadal pojawia się błąd segmentacji.wywoływanie funkcji złożenia z c

W pliku .c mam deklaracja funkcji powiedzmy

int do_shit_in_asm() 

W pliku .asm mam

.extern printf 
.section .data 
     printtext: 
       .ascii "test" 
.section .text 
.global do_shit_in_asm 
.type do_shit_in_asm, @function 

do_shit_in_asm: 
    pushl %ebp 
    movl %esp, %ebp 
    push printtext 
    call printf 
    movl %ebp, %esp 
    pop %ebp 
ret 

Wszelkie wskaźniki komentarze będą mile widziane.

as func.asm -o func.o 

gcc prog.c func.o -o prog 
+23

+1 dla nazwy funkcji –

+33

"Wszelkie wskazówki byłyby mile widziane": int * ptr; – Sapph

+0

@Sapph +1 ale to nie pomaga :)) –

Odpowiedz

16

Zmień push printtext do push $printtext.

Z tego powodu ładujesz wartość z adresu printtext i przesuwając ją, zamiast przesuwać adres. W ten sposób przekazujesz 'test' jako numer 32-bitowy, a nie wskaźnik, a printf próbuje zinterpretować to jako adres i awarię.

9

Jednym z najlepszych sposobów, aby zacząć korzystać z funkcji językowych montaż jest napisać podobną funkcję w C, a następnie zbudować go z przełącznika kompilatora, który generuje listę montażową (-S na GCC). Następnie możesz przestudiować wyniki działania kompilatora i zmodyfikować je w razie potrzeby.

Jest to szczególnie użyteczne w przypadku wywoływania funkcji, takich jak printf, które używają innej konwencji wywoływania (ze względu na zmienną liczbę argumentów). Wywoływanie tych funkcji może być zupełnie inne niż wywoływanie funkcji innych niż varargs.

+1

Bardzo edukacyjny ... ale także typowo bardzo mylący: prawdziwym problemem są szczegółowe dane ABI, które rejestry muszą być zachowane, co oznaczają i jak wchodzą w interakcje z C ABI. poszedł najpierw tą ścieżką, a potem zorientował się, że mój zestaw nie będzie lepszy niż to, co wygenerowałby kompilator, co było dokładnie odwrotnością tego, co próbowałem osiągnąć! – bbum

2

Po tym:

push printtext 
call printf 

Chcecie:

addl $4, %esp 

Dalsze wyjaśnienia:

Ponieważ używasz x86 Linux Zakładam konwencję telefonicznej wymaga wywoływany do czyszczenia Parametry. Ponieważ przed wywołaniem printf naciśniesz wskaźnik, Twój stos zostanie wyłączony o 4 po wydaniu instrukcji o tej funkcji.

Aktualizacja:

Tak, OK, byłem przyzwyczajony do składni Intel tak byłem coraz kolejność argumentów w tył głowy. W rzeczywistości brak addl wróć do esp nie ma znaczenia, ponieważ przywracasz esp poprawnie w pobliżu swojego ret. Mój następny Domyślam się, że ciąg jesteś przechodząc do printf brakuje null terminator ... Pozwól mi zobaczyć, co robi ... gas

Aktualizacja 2:

OK, gas zerowy kończy ciągi dla ty, więc wydaje mi się, że moje drugie przeczucie było złe. Wygląda na to, że znalazłeś problem, więc kwestia jest dyskusyjna.

+0

błąd segmentacji nadal –

+0

Jestem zdezorientowany, ponieważ jestem przyzwyczajony do składni Intela , nie AT & T. Tak naprawdę chcesz 'addl 4 $,% esp' Trzymaj się, pozwól mi spojrzeć jeszcze raz ... – asveikau

+0

@void - Może możesz sprawdzić w edytorze szesnastkowym. ciąg znaków przechodzący do printf zostanie zakończony znakiem null? – asveikau

6

problem było to, że używałem

pushl printtext 

raczej

pushl $printtext 

Thanks wszystkim za pomoc i przepraszam za marnowanie czasu: P

+1

Masz to tuż przed moim wysłaniem. Gratulujemy rozwiązania problemu. :-) –

Powiązane problemy