C i asembler przekazanie tablicy dynanamicznej.

Odpowiedz Nowy wątek
2017-06-19 18:36
0

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.

edytowany 2x, ostatnio: allah, 2017-06-19 18:38

Pozostało 580 znaków

2017-06-19 19:23
Czarny Krawiec
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.

Pozostało 580 znaków

2017-06-19 22:03
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?

Pozostało 580 znaków

2017-06-20 14:44
0

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

Pozostało 580 znaków

2017-06-23 23:26
Biały Programista
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...

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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