Dlaczego ten program nie działa? c + x86 nasm

0

Zamiana małych liter w duże. Program główny w c, funkcja zamieniające litery w x86 nasm.

.\program asdfgDGRtetr
Oryginalny tekst asdfgDGRtetr
Po zmianie tekst asdfgDGRtetr

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void upper(char* tekst);

void main(int argc, char * argv[]){

	char* buf = malloc(sizeof(argv[1])+1);
	strcpy(buf, argv[1]);

	printf("Oryginalny tekst %s\n",buf);
	upper(buf);
	printf("Po zmianie tekst %s\n",buf);

}
section	.text
global	_upper

_upper:
	push	ebp				;prolog
	mov		ebp, esp

	mov		ebx, [ebp+8]	;w ebx adres pierwszej litery stringa
loop:
	mov 	dl, [ebx]		;do dl wprowadzam literę wskazywaną przez ebx
	inc		ebx 			;przesuwam wskaźnik na następną literkę

	test	dl, dl			;jeśli to NULL to idę na koniec
	jz		end

	test	dl, 97			;jeśli mniejsze od 'a' to rozpoczynam pętlę od nowa
	jb		loop

	test	dl, 122 		;jeśli większe od 'z' to rozpoczynam pętlę od nowa
	ja		loop

	sub		dl, 32 			;literka w dl przeszła wyszystkie testy pomyślnie 
	mov 	[ebx-1], dl 	;więc odejmuję 32 żeby zamienić ją w dużą literę
	jmp 	loop 	;a następnie przesyłam wartość dużej litery do pamięci wskazywanej przez ebx-1
end:
	mov     esp, ebp		;epilog
    pop     ebp
    ret

2

Pierwszy lepszy wiersz

malloc(sizeof(argv[1])+1);

jest błędny. Sizeof daje zawsze 4 albo 8 zależnie od architektury, a niezależnie od wielkości stringa, potem jeździsz po przypadkowej pamięci.

Części assemblerowej nie analizowałem, tam też siedzą błędy

1

Instrukcji test możesz używać kiedy sprawdzasz czy dana wartość jest równa 0. Ta instrukcja to jest nic innego jak bitwise AND - AND da Ci 0 tylko wtedy gdy obie wartości tej operacji są równe 0. Czyli to:

test    dl, dl          ;jeśli to NULL to idę na koniec
jz      end

Jest ok, ale to:

test    dl, 97          ;jeśli mniejsze od 'a' to rozpoczynam pętlę od nowa
jb      loop

Już nie. jb patrzy na carry flag, która jest ustawiona kiedy następuje przeniesienie bitów po operacji arytmetycznej. AND nie ustawi Ci tej carry flag dlatego ten test jest tutaj bez sensu. Do porównywania wartości i emulowania if'ów użyj instrukcji cmp + conditional jump. cmp odejmie dwie wartości, a conditional jump ogarnie po flagach powstałych po tych operacjach czy skoczyć czy nie.

0

@Shizzer to było to. Poprawiłem i teraz działa. Dzięki za pomoc

1 użytkowników online, w tym zalogowanych: 0, gości: 1