segment fault po skoku warunkowym

segment fault po skoku warunkowym

Wątek przeniesiony 2020-08-09 02:25 z Edukacja przez cerrato.

P3
  • Rejestracja:prawie 8 lat
  • Ostatnio:9 miesięcy
  • Postów:113
0

Cześć
OS: Linux debian 4.19.0-9-amd64 #1 SMP Debian x86_64 GNU/Linux
Compiler: NASM version 2.14
nasm: nasm -f elf64 zabawa.asm -o zabawa.o
ld: ld zabawa.o -o zabawa

Dawno nic tu nie pisałem :).

Wydawało mi się, że dobrze zacząłem rozumieć temat wywołań i instrukcji warunkowych, ale czegoś mi brakuje :/.
Czy ktoś może mi po ludzku wyjaśnić dlaczego mam segment fault ?

Kopiuj
section .data
msg: db 'Hello world',10
end: db 'Ending program', 10
section .text

global _start

hello_world:

        mov rax, 1
        mov rdi, 1
        mov rsi, msg
        mov rdx , 14

        syscall

        ret

exit:
        mov rax, 1
        mov rdi, 1
        mov rsi, end
        mov rdx, 20

        syscall

       ret
_start:

        mov rax, 10
        mov rdx, 10
        cmp rax, rdx 
        je hello_world
        jne exit

        call hello_world
        mov rax, 60
        xor rdi,rdi
        syscall

        call exit

output:

Kopiuj
./zabawa
Hello world
EnSegmentation fault

Googloawem, nawet zapytałem na SO, ale tam nie wytłumaczą mi prosto ..

Problem w tym, że funkcja po dotarciu do instrukcji ret wraca pod zły adres, ale gdy próbowałem dodać to :

Kopiuj
        push rbp < - prolog
        mov rbp, rsp <- prolog
        mov rsp,0x21 <-  prolog
       
        leave <- na koniec
       ret <- na koniec

ale efekt ciągle taki sam, chce wykonać najprostszy na świecie skok warunkowy, ale nie mam już pomysłu. Używałem ltrace/ptrace i nic.. jedyne na czym operuje to gdb z gef'em

M1
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 4 lata
  • Postów:20
4

w 36 linijce robisz call hello_world ta linijka powoduje, że adres następnej instrukcji tj mov rax,60 jest wrzucany na stos(najczęściej) i kod wskakuje do hello_world, coś się tam wykonuje i instrukcja ret zbiera sobie adres powrotu ze stosu i wskakuje pod ten adres czyli pod adres instrukcji mov rax,60

Jak ty wkonujesz je hello_world w 33 linijce to wskakujesz po prostu do hello_world wypisujesz 14 czy iles tam znaków czyli to Hello world\nEn ("En z Ending Program)
i instrukcja ret chce zebrać adres ze stosu żeby pod niego wskoczyć ale nie ma tam twojego adresu bo nie użyłeś call tylko jest tam jakiś śmieć i masz segmentation fault

edytowany 2x, ostatnio: Madek123
P3
  • Rejestracja:prawie 8 lat
  • Ostatnio:9 miesięcy
  • Postów:113
0

Ok, ale jak nie użyje ret w funkcji hello_word to program wykonuje wszystko jak leci. Czy problem ma związek z konwencją wywołań funkcji: callee/caller ? Moze powinienem wrzucić na stos adres z rip, ale z tego co już ustaliłem nie jest to chyba najlepszy pomysł. Ale skoro podczas wywoływania funkcji adres powrotu jest wrzucany na stos, to czemu w tym przypadku tak nie jest ? coś myle, czuje to :D

edytowany 1x, ostatnio: pain368
M1
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 4 lata
  • Postów:20
3

Jak na końcu hello_world i exit masz instrukcję ret to traktuj to jako "funkcję" i wywołuj tylko używając call hello_world.
jmp, je, jne użyj do rozgałęzień w programie czyli do robienia if'ów.
Załóżmy, że chcesz uzyskać taki przebieg:

Kopiuj
__start(){
if(rax == rdx) 
   hello_world()

exit(); 

return;
}

to funkcję hello_world() i funkcję exit() wywołujesz używając call a tego ifa tworzysz używając skoków np.

Kopiuj
cmp rax,rdx
jne a                 <--- albo zamiast tworzenia etykiety 'a' makro, że skaczesz jedną instrukcję dalej nie wiem jak to sie robi w nasmie
call hello_world
a: call exit
ret

///edit
1* Konwencja wywołań pojawia się wtedy gdy do funkcji przekazujesz jakieś argumenty i musisz się zastanowić kto ma posprzątać po tym, albo gdzie je przekazać ty do swoich funkcji nic nie przekazujesz
2* W tym przypadku adres nie był na stosie bo instrukcja jmp to w skrócie weź adres z argumentu i daj go do rip, a instrukcja call w skrócie to: daj rip na stos czyli adres następnej instrukcji, a potem wykonaj jmp do argumentu

edytowany 5x, ostatnio: Madek123
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)