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