Koprocesor w asemblerze

0

Witam. Mam do zrobienia taką funkcję w asemblerze tg(2*x) nie działa mi to poprawnie :( tzn po obliczeniu program się wykrzacza oraz chyba nie do końca mi dobrze liczy;/. Podobno nie wszystkie programy działają pod win 7 tylko np pod XP. Oto kod programu :

;Aplikacja ?wiczenia 8 "Koprocesor i jednostka MMX"
.586P
.MODEL flat, STDCALL
;--- stale ---
;--- z pliku windows.inc ---
STD_INPUT_HANDLE                     equ -10
STD_OUTPUT_HANDLE                    equ -11
;--- z pliku fpu.inc ---
SRC1_FPU    EQU   1
SRC1_REAL   EQU   2
SRC1_DMEM   EQU   4
SRC1_DIMM   EQU   8
SRC1_CONST  EQU   16
SRC2_FPU    EQU   256
SRC2_REAL   EQU   512
SRC2_DMEM   EQU   1024
SRC2_DIMM   EQU   2048
SRC2_CONST  EQU   4096
;--- funkcje API Win32 ---
;--- z pliku  user32.inc ---
CharToOemA PROTO :DWORD,:DWORD
;--- z pliku kernel32.inc ---
GetStdHandle PROTO :DWORD
FreeConsole PROTO
ReadConsoleA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
WriteConsoleA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
ExitProcess PROTO :DWORD
wsprintfA PROTO C :VARARG
lstrlenA PROTO :DWORD
FpuFLtoA PROTO :DWORD,:DWORD,:DWORD,:DWORD
    ;;lpSrc1    // pointer to an 80-bit REAL number
    ;;lpSrc2    // pointer to, or value of, 2nd parameter
    ;;lpszDest  // pointer to destination of result
    ;;uID       // ID flags for sources and format
    ;;uID - One of the SRC1_? flags must be OR'ed with only one of the SRC2_? flags and OR?ed with one of the STR_? flags. 
    ;;(The STR_REG flag does not need to be OR?ed if the string must be returned in decimal format; that is the default.)
    ;;uID Flag     Meaning
    ;;SRC1_FPU     Src1 is already on the FPU
    ;;SRC1_REAL    Src1 is a pointer to an 80-bit REAL number
    ;;SRC2_DMEM    Src2 is a pointer to a 32-bit signed integer
    ;;SRC2_DIMM    Src2 is a 32-bit signed integer
    ;;STR_REG      The string must be returned in decimal format
    ;;STR_SCI      The string must be returned in scientific notation
    ;;Return Values:
    ;;If the source is considered a valid REAL number, the converted string will be transferred to the specified destination and EAX will be non-zero.
    ;;If the function fails, EAX will be zero and the null-terminated string ERROR will be placed at the specified destination.
    ;;The source is never modified, whether it is in memory or on the FPU.
;-------------
includelib user32.lib
includelib kernel32.lib
includelib masm32.lib
includelib fpu.lib
;-------------

;-------------
;macra:
PODAJDESKRKONSOLI MACRO handle, deskrypt
	invoke GetStdHandle, handle								; wywolanie funkcji GetStdHandle
	mov deskrypt,EAX 										; deskryptor bufora konsoli
ENDM

DRUKUJ_ MACRO nazwa, rozmiar 								; macro do wyswietlania napisow
	invoke CharToOemA, OFFSET nazwa, OFFSET nazwa			; konwersja polskich znakow
    invoke WriteConsoleA,hout,OFFSET nazwa,rozmiar,rout,0	; wyswietlenie napisu
ENDM
;dane
_DATA SEGMENT

	hout	DD	?
	hinp	DD	?
	rout	DD	0 											
	rinp	DD	0
	
	bufor	DB	128 dup(?)
	rbuf	DD	128
	
	odstep  DB	0Dh,0Ah,0									; pusty wiersz
	
	naglow	DB	0Dh,0Ah,"Autor aplikacji ktos.",0Dh,0Ah,0
	rozmN	DD	$ - naglow

    opis   	DB 0Dh,0Ah,"Funkcja y= tg(2*x).",0Dh,0Ah,0
    opisR   DD $ - opis	
	
	zap1   DB 0Dh,0Ah,"Proszę wprowadzić 'x':",0
    zapR1   DD $ - zap1	

    error_   DB "Brak dostępu do koprocesora.",0
    err_     DD $ - error_

    wyn     DB " f(x)=%s",0
	
	x		DD	? 
	cons	REAL10	2.0
    

    liczba  DD 4*256+5          	; 1 - ilosc znakow przed przecinkiem   5 - ilosc znakow po przecinku 
	wiersz  DB 6 dup(?)
	
	stan	DB	108 dup(0) 		; 108 = 7*4 bajty + 8*10 bajtów
	stan2	DB	108 dup(0) 		; 108 = 7*4 bajty + 8*10 bajtów

_DATA ENDS
;---
_TEXT SEGMENT

ScanInt	PROC
		;; funkcja ScanInt przekształca ciąg cyfr do liczby, którą jest zwracana przez EAX
		;; argument - zakończony zerem wiersz z cyframi
		;; rejestry: EBX - adres wiersza, EDX - znak liczby, ESI - indeks cyfry w wierszu, EDI - tymczasowy
		;--- początek funkcji
			push	EBP
			mov		EBP, ESP	; wskaźnik stosu ESP przypisujemy do EBP
		;--- odkładanie na stos
			push	EBX
			push	ECX
			push	EDX
			push	ESI
			push	EDI
		;--- przygotowywanie cyklu
			mov		EBX, [EBP+8]
			push	EBX
			call	lstrlenA
			mov		EDI, EAX	;ilość znaków
			mov		ECX, EAX	;ilość powtórzeń = ilość znaków
			xor		ESI, ESI	; wyzerowanie ESI
			xor		EDX, EDX	; wyzerowanie EDX
			xor		EAX, EAX	; wyzerowanie EAX
		;--- cykl --------------------------
			@@pocz:
				cmp	BYTE PTR [EBX+ESI], 02Dh	;porównanie z kodem -
				jne	@@et1
				mov	EDX, 1
				jmp	@@nast
			@@et1:
				cmp	BYTE PTR [EBX+ESI], 030h	;porównanie z kodem 0
				jae	@@et2
				jmp	@@nast
			@@et2:
				cmp	BYTE PTR [EBX+ESI], 039h	;porównanie z kodem 9
				jbe	@@et3
				jmp	@@nast
			;----
			@@et3:	
				push	EDX	; do EDX procesor może zapisać wynik  
				mov	EDI, 10
				mul	EDI		;mnożenie EAX * EDI
				mov	EDI, EAX	; tymczasowo z EAX do EDI
				xor	EAX, EAX	;zerowani EAX
				mov	AL, BYTE PTR [EBX+ESI]
				sub	AL, 030h	; korekta: cyfra = kod znaku - kod 0	
				add	EAX, EDI	; dodanie cyfry
				pop	EDX
			@@nast:	inc	ESI
			loop	@@pocz
		;--- wynik
			or	EDX, EDX	;analiza znacznika EDX
			jz	@@et4
			neg	EAX
		@@et4:	
		;--- zdejmowanie ze stosu
			pop	EDI
			pop	ESI
			pop	EDX
			pop	ECX
			pop	EBX
		;--- powrót
			pop	EBP
			ret
	ScanInt	ENDP
start:
    pushfd
    pushad
;-------- sprawdzanie, czy jest koprocesor
	fsave stan					; stan koprocesora (FPU)
	fwait  					; tylko dla procesora 286 i 386 po każdej instrukcji
	finit						; ustawia Tag Word w "1111111111111111"
	fsave stan2				      ; stan koprocesora (FPU)
	lea ESI,stan2
	lodsd						; Control Word ==> EAX
	lodsd						; Status Word ==> EAX
	lodsd						; Tag Word ==> EAX
	cmp AX,0FFFFh											
		jne koniec											
PODAJDESKRKONSOLI -11, hout			; deskryptor wyjściowego bufora konsoli
PODAJDESKRKONSOLI -10, hinp			; deskryptor wejściowego bufora konsoli (klawiatura)

DRUKUJ_ naglow, rozmN				; wyswietlenie naglowka/autora
DRUKUJ_ opis, opisR				; wyswietlenie zadania ktore wykonuje program 
DRUKUJ_ zap1, zapR1 
	mov [bufor],0				; czyszczenie bufora
	invoke ReadConsoleA, hinp, OFFSET bufor, rbuf, OFFSET rinp, 0 ; wywołanie funkcji 'ReadConsoleA' wczytującej wprowadzany znak
	push	OFFSET bufor			; wkładanie bufora na stos
	invoke	ScanInt			; wywołanie podprogramu ScanInt zamieniającego tekst na liczbe
	mov x,EAX 

    ;--------obliczenia----
    fld     cons                        				
    fild	x 												
    fmul													
    fptan
                                  						
    ;-------- wyświetlenie wyniku --------
    invoke  FpuFLtoA,0,ADDR liczba,ADDR wiersz,1 OR 1024
    invoke  wsprintfA,OFFSET bufor,OFFSET wyn,ADDR wiersz
	mov rbuf,EAX
DRUKUJ_ bufor, rbuf
DRUKUJ_ odstep, 2
	jmp koniec

koniec:
;----------- zakończenie procesu ---------------
	finit
	frstor stan
	fwait
	popad
	popfd
	invoke ExitProcess, 0
_TEXT ENDS

END start 
0

;-------- sprawdzanie, czy jest koprocesor
To nie ma absolutnie sensu.
Masz 32-bitowy program pod Windows. Tymczasem już Windows 95 wymagał obecności koprocesora.

Być może jest możliwa próba uruchomienia tego programu bez koprocesora na jakimś Windows NT 3.1, ale to prehistoria.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.