C i asembler przekazanie tablicy dynanamicznej.

1

Witam,
Pisze program, który stworzony jest z dwoch modułów. Moduł główny stworzony jest w C. Jego zadaniem jest pobranie od użytkownika danych, które zostaną przekazane do modułu napisanego w asemblerze. Moduł w asemblerze wykonuje obliczenia, a następnie zwraca wyniki, które zostają wypisane przez moduł główny.

Oto moj kod w C:


    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    extern "C" near void licz_sr( int* );
    extern "C" near void licz_znaki( char* );
    
    int *tablica_liczb_dynamiczna;
    char tablica_znakow[28]; //[0] = ilosc, [1] = kod szukany, [27] = ilosc wystapien
    int wielkosc_tablicy = 0;
    int kod;
    
    int menu(), losuj_liczby(), losuj_znaki(), licz_srednia(), sprawdz_ilosc_znakow();
    void wczytaj_liczby(), wczytaj_znaki();
    
    int main() {
    	srand(time(NULL));
    
    	//tablica_liczb[0] = 5;
    	tablica_znakow[0] = 25;
    	menu();
    	
    	return 0;
    }
    
    int menu(){
    
    	printf("\n\n\nCo mam zrobic?\nW = Wyliczyc srednia z losowej tablicy\nP = Policzyc ilosc znakow w losowej tablicy\nX = Wyjsc z programu\n");
    
    	kod = getchar();
    	getchar();
    
    	if (kod == 87 || kod == 119) {
    		//losuj_liczby();
    		wczytaj_liczby();
    		//licz_srednia();
    	}
    	else if (kod == 80 || kod == 112){
    		//losuj_znaki();
    		wczytaj_znaki();
    		sprawdz_ilosc_znakow();
    	}
    	else if (kod == 88 || kod == 120){
    		return 0;
    	}
    	menu();
    }
    
    void wczytaj_liczby()
    {
    	printf("Ile znakow wprowadzic? ");
    	scanf("%d",&wielkosc_tablicy);
    	printf("wielkosc tab: "); printf("%d",wielkosc_tablicy);
    
    	tablica_liczb_dynamiczna = (int*)malloc(wielkosc_tablicy * sizeof(int));
    
    	for(int i = 0; i < wielkosc_tablicy; i++){	
    		tablica_liczb_dynamiczna[i] = NULL;
    	}
    
    	printf("\n\nWczytaj liczby:");
    
    	for(int j = 0; j < wielkosc_tablicy; j++)
    
    	{
    		scanf("%d", &tablica_liczb_dynamiczna[j]);
    
    		printf("\n");
    		printf("%d", j);printf("element tab "); printf("%d",tablica_liczb_dynamiczna[j]);
    		printf("\n");
    		tablica_liczb_dynamiczna[j] = tablica_liczb_dynamiczna[j]-48;
    	}
    	licz_srednia();
    }
    /*
    void wczytaj_znaki()
    
    {
    
    	for (int i =2; i < tablica_znakow[0]+2; i++)
    
    	{
    
    		tablica_znakow[i] = NULL;
    
    	}
    
    	printf("\n\nWczytaj znaki:");
    
    	char polecenie[25];
    
    	fgets( polecenie, 25, stdin );
    
    	for (int j =2; j < tablica_znakow[0]+2; j++)
    
    	{
    
    		tablica_znakow[j] = polecenie[j-2];
    
    	}
    
    }
    */
    
    
    int licz_srednia()
    
    {
    	licz_sr(tablica_liczb_dynamiczna);
    
    
    
    	//printf("\n\nSrednia jest rowna: "); printf("%c", tablica_liczb[6]+48); printf(", a reszta jest rowna: "); printf("%c", tablica_liczb[7]+48);
    
    	printf("\n\nSrednia jest rowna: "); printf("%c", tablica_liczb_dynamiczna[6]+48); printf(", a reszta jest rowna: "); printf("%c", tablica_liczb_dynamiczna[7]+48);
    
    	//cout << "Srednia jest rowna: " << tablica_liczb_dynamiczna[6]+48 << ", a reszta: " << tablica_liczb_dynamiczna[7]+48 << endl;
    
    	return 0;
    
    }
    
    
  /* int sprawdz_ilosc_znakow()
    
    {
    
    	printf("\n\nWystapienia jakiego znaku mam liczyc? ");
    
    	tablica_znakow[1] = getchar();
    
    	getchar();
    
    	//printf("\n\n");
    
    	licz_znaki(tablica_znakow);
    
    	
    
    	printf("\nZnak \""); printf("%c", tablica_znakow[1]); printf("\" wystapil "); printf("%c", tablica_znakow[27]+48); 
    
    	if (tablica_znakow[27] != 1)		printf(" razy.");
    
    	else											printf(" raz.");
    
    }*/

I kod w asemblerze:


 .model small, C


    Dane			SEGMENT
    
    Tablica			DB			(?)
    Ilosc			DB			(?)
    
    Dane			ENDS
    
    
    /*PUBLIC licz_znaki
    
    .code
    
    
    licz_znaki    PROC near
    
    
    			push	bp
    			mov		bp, sp
    			mov		di, [bp+4]
    			; [bp+4] = adres
    			; [di] = liczba
    			; [bp+12] = tab[1]
    			; [bp+16] = tab[2]
    			; [bp+20] = tab[3]
    			; [bp+24] = tab[4]
    			xor		cx, cx
    			mov		cl, [di]
    			inc		di
    			;inc		di
    			xor		ax, ax
    			xor		bx, bx
    			xor		dx, dx
    			mov		ah, [di]			;w ah jest znak, którego szukamy
    			inc		di
    			;inc		di
    Petla_z:
    			mov		al, [di]			;w ah jest aktualny znak z tablicy
    			cmp		al, ah
    			jz			Dodaj_do_wyniku
    			Powrot_do_petli:
    			inc		di
    			;inc		di
    			loop		Petla_z
    
    Dodaj_do_wyniku:
    			jcxz		Koncowka
    			inc		bx				;bh przechowuje ilosc wystapien
    			jmp		short	Powrot_do_petli
    			
    Koncowka:
    			mov		[di], bx
    			
    			pop		bp
    			ret
    
    licz_znaki ENDP
    */

    PUBLIC licz_sr
    
    .code
    
    
    licz_sr    PROC near
    
    
    			push	bp
    			mov		bp, sp
    			mov		di, [bp+4]
    			mov		bx, [di]
    			; [bp+4] = adres
    			; [di] = liczba
    			; [bp+12] = tab[1]
    			; [bp+16] = tab[2]
    			; [bp+20] = tab[3]
    			; [bp+24] = tab[4]
    			xor		cx, cx
    			mov		cl, [di]
    			inc		di
    			inc		di
    			xor		ax, ax
    			xor		dx, dx
    Petla_l:
    			add		ax, [di]
    			inc		di
    			inc		di
    			loop		Petla_l
    			
    			div		bx
    			
    			mov		[di], ax
    			inc		di
    			inc		di
    			mov		[di], dx		;wj
    			
    			pop		bp
    			ret
    
    licz_sr ENDP
    
    
    end

Stworzyłem ten program z wykorzystaniem tablicy stałej. Pobierał on 5 elementow do 7 elementowej tablicy. Następnie operacje były wykonywane i zwracane za pomocą indeksów [5] i [6], a następnie wypisywane w module C.
Próbowałem analogicznie z tablicą dynamiczną, ale nie wiem jak ją przekazać do modułu asemblera.
Mało istotne części kodu zakomentowałem.

0

Nawet mi się nie chciało za dużo czytać, ale przekazujesz wskaźnik ok, ale wielkość wskaźnika może być 32 lub 64 bitowa, a ty tam na 16 bitach jedziesz.

Jak przekażesz ten wskaźnik, to go ściągasz ze stosu, zwykle [ebp+8] (ramka stosu, adres powrotu+4, pierwszy argument+8), potem lea eax, adres tej tablicy(ze stosu) + wielkość_elementu * i-ty-element
a z tego potem [eax] i masz element wyciągnięty z tablicy.

0
Czarny Krawiec napisał(a):

Nawet mi się nie chciało za dużo czytać, ale przekazujesz wskaźnik ok, ale wielkość wskaźnika może być 32 lub 64 bitowa, a ty tam na 16 bitach jedziesz.

16-bitowe wskaźniki też mogą być, zależy czym to kompiluje.
I to jest istotne pytanie: jaki kompilator? jaki asembler?

0

Asembler 16-bitowy, a kompilator Borland C/C++ pod DOS'em.

1
allah napisał(a):

Asembler 16-bitowy, a kompilator Borland C/C++ pod DOS'em.

w C masz underline przed nazwami, zatem te deklaracje;
extern "C" near void licz_sr( int* );
extern "C" near void licz_znaki( char* );

oznaczają że w asm musisz ponazywać te funkcje:
_licz_sr oraz _licz_znaki

inaczej linker tego nie znajdzie...

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