• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

FASM - długość string'a

Object Storage Arubacloud
0 głosów
399 wizyt
pytanie zadane 17 listopada 2018 w Assembler przez DeBos123 Nałogowiec (44,950 p.)

Witam, chciałbym w fasm'ie sprawdzić długość string'a i dostaję "segmentation fault".

Napisałem taki kod:

strlen:
	mov ebx,0    ;ustawiam ebx na 0
strlen_loop:
	cmp byte [eax+ebx],0    ;sprawdzam czy byte o index'ie ebx ma wartość zero
	inc ebx    ;inkrementuje wartość ebx
	jne strlen_loop    ;jeżeli ten byte jest różny od zera wracam do strlen_loop
	ret    ;kończę funkcje

dalej w kodzie "wywołuję funkcje" w taki sposób:

	mov eax,[esp+4]    ;ustawiam eax na pierwszy argument (nazwę) programu
	call strlen    ;wywołuje funkcje
	push ebx    ;wynik funkcje daję na stos

później próbuję wypisać tekst:

	mov eax,4    ;4 - sys_write
	mov ebx,0    ;0 - stdout
	mov ecx,[esp+4]    ;pierwszy argument programu
	pop edx    ;ustawiam edx na to co wcześniej dałem na stos
	int 80h    ;i próbuję wypisać tekst

niestety nie znam się debugowaniu fasm'a, więc wiem tylko tyle, że błąd jest przy sprawdzaniu drugiego byte'a w string'u.

1 odpowiedź

+1 głos
odpowiedź 17 listopada 2018 przez Eryk Andrzejewski Mędrzec (164,260 p.)
wybrane 17 listopada 2018 przez DeBos123
 
Najlepsza

Nie wiem ile to może pomóc, ale tak na szybko:

mov eax,[esp+4]

Zamień powyższą linijkę na:

mov eax, esp+4

Choć nie wiem czy fasm toleruje taki kod, możesz w takim wypadku spróbować tak:

mov eax, esp
add eax, 4

Z tego co widzę to korzystasz z [] dwukrotnie, a adres każdej litery to adres pierwszej literki (czyli to esp + 4) + przesunięcie w samym napisie (ebx), czyli dana litera znajduje się pod adresem (eax + esp + ebx). Ty natomiast chyba do eax zapisujesz nie adres, ale wartość pod tym adresem i tę wartość sumujesz z przesunięciem. Jeśli źle myślę, możesz mnie poprawić. wink

komentarz 17 listopada 2018 przez DeBos123 Nałogowiec (44,950 p.)

Spróbowałem usunąć nawiasy i przy kompilacji programu dostałem taki błąd:

flat assembler  version 1.71.59  (16384 kilobytes memory)
main.asm [30]:
	mov eax,esp+4
processed: mov eax,esp+4
error: extra characters on line.

Co do samych nawiasów to moim zdaniem moje rozwiązanie powinno działać, ponieważ jeżeliby porównać kod do C to wyglądałoby to mniej więcej tak:

esp+4 => (esp => argc), więc esp+4 to wskaźnik na pierwszy argument

[esp+4] => wartość wskaźnika na pierwszy argument, czyli (wskaźnik na pierwszy znak w string'u?)

[esp+4]+ebx => (wskaźnik na pierwszy znak w string'u?) przesunięty o ebx byte'ów, czyli znak o index'ie ebx

[[esp+4]+ebx] => wartość wskaźnika, czyli po prostu znak o index'ie ebx

komentarz 17 listopada 2018 przez Eryk Andrzejewski Mędrzec (164,260 p.)

Co do błędu to poniżej napisałem inny kod, który możesz wypróbować. Ten już nie powinien wyrzucić błędu.

Ah, rozumiem już, Tobie chodzi o char* argv[]. To poczekaj, postaram się pomyśleć.

komentarz 17 listopada 2018 przez DeBos123 Nałogowiec (44,950 p.)
edycja 17 listopada 2018 przez DeBos123

Ah, rozumiem już, Tobie chodzi o char* argv[]

Jak już to odpowiednik char** argv[].

Z tego co wiem to rejestr esp przechowuje wskaźnik na argc z C, a esp+(n*4) przechowuje argv[n] albo wskaźnik na to chyba, już się trochę pogubiłem.

komentarz 17 listopada 2018 przez DeBos123 Nałogowiec (44,950 p.)

Choć nie wiem czy fasm toleruje taki kod, możesz w takim wypadku spróbować tak:

Toleruje, ale efekt ten sam (sprawdziłem).

komentarz 17 listopada 2018 przez Eryk Andrzejewski Mędrzec (164,260 p.)

@DeBos123,
Nie, char* argv[] lub char** argv.

Parametr funkcji argc to jest tylko zwykła zmienna typu int, nie ma żadnych wskaźników na nią. Wskaźniki dotyczą argv, czyli tej "tablicy" argumentów.

komentarz 17 listopada 2018 przez DeBos123 Nałogowiec (44,950 p.)

Nie, char* argv[] lub char** argv.

Rzeczywiście, mój błąd.

Parametr funkcji argc to jest tylko zwykła zmienna typu int, nie ma żadnych wskaźników na nią.

Tak, w C jest to zwykły int, ale chodziło mi o to, że w fasm'ie w rejestrze esp jest chyba wskaźnik na int'a, a ten int jest odpowiednikiem argc z C.

komentarz 17 listopada 2018 przez Eryk Andrzejewski Mędrzec (164,260 p.)

Uch, strasznie dawno nie pisałem niczego w języku asemblera, w dodatku ciężko mi się dzisiaj myśli, więc się trochę namęczyłem - ale działa. Mój przerobiony kod:

format ELF executable
entry _start

segment	readable executable

_start:
    mov ecx, [esp + 4]

    call strlen
    
    mov eax, 4 
    mov ebx, 0
    int 80h 

    mov eax, 1
    int 0x80

strlen:
    mov edx, 0
    strlen_loop:
        cmp byte [ecx + edx], 0
        je strlen_end
        inc edx
        jmp strlen_loop
    strlen_end:
        inc edx
        ret

Co zmieniłem? Podstawowa sprawa - w Twoim kodzie instrukcja porównująca cmp i skok warunkowy jne były rozdzielone inną instrukcją, więc wartość rejestru flagowego ZF mogła ulec zmianie (i pewnie uległa, skoro program się wysypywał). Ja zawsze jak coś piszę, to skoki warunkowe umieszczam bezpośrednio za cmp.

Zmieniłem też rejestry eax i ebx na ecx i edx (żeby nie trzeba było później kombinować w przekazywanie wartości przez stos i tak dalej).

komentarz 17 listopada 2018 przez DeBos123 Nałogowiec (44,950 p.)

Dziękuję za pomoc, teraz działa bez problemu.

wartość rejestru flagowego ZF mogła ulec zmianie

Mógłbyś to bardziej rozwinąć? Chodzi mi o to, po co instrukcja inc (która tylko inkrementuje wartość) zmieniła wartość flagi ZF.

Albo to co zauważyłem przed chwilą, czyli instrukcja ret zmienia (albo nawet zeruje) wartość ebx.

komentarz 17 listopada 2018 przez Eryk Andrzejewski Mędrzec (164,260 p.)

Flaga ZF jest ustawiana (czyli ma wartość 1) w momencie, gdy wynik ostatniej operacji jest równy zero. Natomiast w przeciwnym wypadku, flaga nie jest ustawiona (ma wartość 0).

Natomiast co do drugiego przypadku to szczerze mówiąc nie wiem, na pewno tak się dzieje? Może procesor wykorzystuje rejestr ebx do pobrania ze stosu adresu wywołania, żeby poźniej do niego skoczyć.

@EDIT

Sprawdziłem u siebie i ret nie modyfikuje zawartości EBX (ustawiłem sobie dla rejestru EBX przed instrukcją ret, a po wywołaniu funkcji dałem int3 i sprawdziłem w debuggerze - ebx zachową swoją wartość). Może się pomyliłeś?

komentarz 17 listopada 2018 przez DeBos123 Nałogowiec (44,950 p.)

To jest kod funkcji strlen:

strlen:
	mov ebx,0
	strlen_loop:
		cmp byte [eax+ebx],0
		je strlen_end
		inc ebx
		jmp strlen_loop
	strlen_end:
		inc ebx
		ret

A to jest kod, którym chcę wypisać ten tekst:

		mov eax,[esp+4]
		call strlen
		push ebx

		mov eax,4
		mov ebx,0
		mov ecx,[esp+4]
		pop edx
		int 80h

Czyli wywołuje funkcje strlen, ona ustawia ebx na długość napisu, wrzucam na stos wartość ebx, a później ściągam ją do edx.

Wiem, że po drodze modyfikuje wartość rejestru ebx, ale mi chodzi o wartość, która jest na stosie, a ona powinna (przynajmniej mi się tak wydaje) zostać niezmieniona.

Podobne pytania

0 głosów
1 odpowiedź 242 wizyt
pytanie zadane 8 maja 2023 w Assembler przez Saskus Nowicjusz (150 p.)
+1 głos
0 odpowiedzi 128 wizyt
pytanie zadane 10 grudnia 2018 w Assembler przez DeBos123 Nałogowiec (44,950 p.)
+1 głos
1 odpowiedź 625 wizyt
pytanie zadane 5 listopada 2018 w Assembler przez DeBos123 Nałogowiec (44,950 p.)

92,568 zapytań

141,422 odpowiedzi

319,642 komentarzy

61,957 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...