Łączenie assemblera i C++

0

Witam, mam za zadanie napisać w assemblerze funkcję, która wyznacza liczbę cyfr zadanej liczby. Liczbę podaję w C++, przeskakuję do funkcji w assemblerze i wracam. I mam problem z kodem, który napisałam, bo o ile dla liczb jednocyfrowych zwraca mi poprawną liczbę, to przy większych dostaję błąd w obliczeniach zmiennoprzecinkowych i nie bardzo wiem dlaczego. Bardzo proszę o pomoc

 #include<iostream>

using namespace std;
extern "C" int ile(int);
int main()
{
	int a,s;
	cin>>a;
	s=ile(a);
	cout<<s;


return 0;
}
 global ile
section .text
ile:

mov rcx,1 ;licznik ilości cyfr

cmp rdi,10 
jg _petla
jl _koniec

mov rax,0
mov rax,rdi 
mov r9,10
_petla:
	inc rcx
	div r9

	cmp rax,10
	jg _petla	
	jl _koniec

_koniec:
mov rax,0
mov rax,rcx
ret
1

Odpal to pod debugerem?

1

Btw, do tego zadania wystarczy policzenie logarytmu - nie musisz się bawić w żadne pętle.

0
Patryk27 napisał(a):

Btw, do tego zadania wystarczy policzenie logarytmu - nie musisz się bawić w żadne pętle.

Logarytm pod asmem to nie do końca tak łatwo.

Najłatwiej po prostu sprawdzać w jakim zakresie to jest liczba.
od 0 do 9 jest jedna cyfra.
od 10 do 99 dwie.
od 100 do 999 trzy.
i tak do dziesięciu, więcej w 32-bitowym incie się nie zmieści.

zastanowić się, co z liczbami ujemnymi.

0
Azarien napisał(a):
Patryk27 napisał(a):

Btw, do tego zadania wystarczy policzenie logarytmu - nie musisz się bawić w żadne pętle.

Logarytm pod asmem to nie do końca tak łatwo.

Najłatwiej po prostu sprawdzać w jakim zakresie to jest liczba.
od 0 do 9 jest jedna cyfra.
od 10 do 99 dwie.
od 100 do 999 trzy.
i tak do dziesięciu, więcej w 32-bitowym incie się nie zmieści.

zastanowić się, co z liczbami ujemnymi.

@Azarien widzę że spałeś na matematyce i/lub nie znasz asma.
Patryk27 ma rację, wystarczy policzyć logarytm i w asmie jest to bardzo proste:
korzystając z równania log(10)2 * log(2)x = log(10)x.

Przykładowy kod Cpp

 #include <iostream>

struct my{
	int number;
	double result;
};

using namespace std;
extern "C" void ile(my *);
int main(){
	my a;
	cin >> a.number;
	ile(&a);
	int szukane = a.result;
	cout << "Liczba cyfr w liczbie: " << a.number << " to: " << szukane+1 << endl;
	return 0;
}

Przykładowy kod asma(nasm) :

 global ile
section .text
    ile:
        finit
        fld1
        fild dword [eax]
        fyl2x
        fldlg2
        fmul st1
        add eax,4
        fst qword [eax]
    ret

0

Powyższy kod na 32-bitowe maszyny, jeżeli będzie potrzeba skorzystać z 64bitów to należy lekko zmodyfikować.

0
Chory Programista napisał(a):

Powyższy kod na 32-bitowe maszyny, jeżeli będzie potrzeba skorzystać z 64bitów to należy lekko zmodyfikować.

Mówisz?
System 32-bitowy:

c:\myprogs\cpp\chory>b
123
Liczba cyfr w liczbie: 123 to: -2147483647

Dziękuję, nie mam więcej pytań :-)
Problem wynika z niezgodności konwencji wywołania: w eax nie ma parametru, parametr domyślnie jest na stosie.

Ale twój kod w ogóle jest dziki. Funkcja powinna przyjmować inta (albo lepiej unsigned inta) i zwracać takiegoż inta.
Twój kod przyjmuje strukturę, a wynik wypełnia w double, i jeszcze trzeba doń dodać 1. WTF?

0

"nigdzie nie było powiedziane że wolno korzystać z fpu, zresztą dokładność tych twoich obliczeń też jest przez to ograniczona"
1.Nigdzie nie było napisane że nie wolno korzystać z fpu
2. Dokładność obliczeń: tak? Wytłumacz mi to pięknie i podaj przykład w którym to się nie sprawdzi o ile łaska.

@Azarien
Tak to prawda, powienienem dodać, że chodzi mi o system linuxowy, lub zrobić to w inny sposób. Jak chcesz możesz dostosować do windowsa nikt Cię nie powstrzymuje.

 $ ./digits
2
Liczba cyfr w liczbie: 2 to: 1
$ ./digits                                       
9
Liczba cyfr w liczbie: 9 to: 1
$ ./digits                                       
10
Liczba cyfr w liczbie: 10 to: 2
$ ./digits              
99
Liczba cyfr w liczbie: 99 to: 2
$ ./digits                                       
101
Liczba cyfr w liczbie: 101 to: 3
$ ./digits                            
999
Liczba cyfr w liczbie: 999 to: 3
$ ./digits                                       
1000
Liczba cyfr w liczbie: 1000 to: 4

Dziękuję ;)
Ten algorytm pobiera minimum taktów procesora, aby wykonać to zadanie i jest maksymalnie prosty. To chyba wszystko.

0

Ten algorytm pobiera minimum taktów procesora, aby wykonać to zadanie i jest maksymalnie prosty. To chyba wszystko.

Szkoda tylko, że wykłada się na zerze. Tak to jest jak się nadmiernie ufa w „maksymalnie proste” rozwiązania.

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