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.

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