[ Pobierz całość w formacie PDF ]
; %7łycie przestaje być
; wygodne. DOS już nam nie ustawi
; DS=ES=CS. A nasze dane sÄ… w
; segmencie kodu, stad ustawiamy DS=CS
; W programie typu .com to na pewno
; nie zaszkodzi.
finit ; zawsze o tym pamiętaj !!!!
fild qword ptr [dzielna] ; Å‚adujemy dzielnÄ…. st(0) = 1234DD
fild qword ptr [dzielnik] ; Å‚adujemy dzielnik. st(0) = 10000h,
; st(1) = 1234DD
fdivp ; dzielimy. st(1) := st(1)/st(0) i
; zdejmij. st(0) ~= 18.2
fstp tbyte ptr [iloraz] ; zapisujemy st(0) do pamięci i
; zdejmujemy ze stosu
; jeśli nie chcesz wyświetlania, usuń te 3 linijki niżej:
mov di, offset iloraz ; DI=adres zmiennej zawierajÄ…cej wynik
piszd80 ; wyświetl wynik
nwln ; przejdz do nowej linii
mov ax, 4c00h
int 21h
end start
Teraz wersja dla NASMa. O tym, jak NASMem zrobić program typu .exe napisane jest w jego dokumentacji.
Wymaga to przede wszystkim stworzenia własnego segmentu stosu i nakierowanie na niego rejestrów SS:SP.
Trzeba mieć też odpowiedni linker, np. VAL. Można jednak użyć jednego z plików dołączonych do mojej
biblioteki i tak też zrobimy.
(przeskocz ten program w wersji NASMa)
; NASM:
; z wyświetlaniem:
; nasm -f obj -o fpu1.obj fpu1.asm
; val fpu1.obj,fpu1.exe,,bibl\lib\std_bibl.lib,
; bez wyświetlania:
; nasm -f obj -o fpu1.obj fpu1.asm
; val fpu1.obj,fpu1.exe,,,
; częściowa zgodność z TASMem:
%include "bibl\incl\nasm\do_nasma.inc"
; jeśli nie chcesz wyświetlania, usuń tą linijkę niżej:
%include "bibl\incl\nasm\std_bibl.inc"
.model small
.stack 400h
.code
..start:
mov ax, cs
mov ds, ax
mov es, ax ; konieczne w programie typu .exe !
; %7łycie przestaje być
; wygodne. DOS już nam nie ustawi DS=ES=CS.
; A nasze dane sÄ… w
Bogdan Drozdowski 57
Bogdan Drozdowski Język asembler dla każdego 2007-11-12
; segmencie kodu, stÄ…d ustawiamy DS=CS.
; W programie typu .com to na pewno nie
; zaszkodzi.
finit ; zawsze o tym pamiętaj !!!!
fild dword [dzielna] ; Å‚adujemy dzielnÄ…. st(0) = 1234DD
fild dword [dzielnik]; Å‚adujemy dzielnik. st(0) = 10000h,
; st(1) = 1234DD
fdivp st1, st0 ; dzielimy. st(1) := st(1)/st(0) i
; zdejmij. st(0) ~= 18.2
; FASM: fdivp st(1)
fstp tword [iloraz] ; zapisujemy st(0) do pamięci i zdejmujemy
; ze stosu
; jeśli nie chcesz wyświetlania, usuń te 3 linijki niżej:
mov di, iloraz
piszd80 ; wyświetl wynik
nwln ; przejdz do nowego wiersza
mov ax, 4c00h
int 21h
align 8 ; NASM w tym miejscu dorobi kilka NOP-ów
; (instrukcji nic nie robiÄ…cych, ale
; zabierających czas), aby adres dzielił się
; przez 8 (patrz dalej).
dzielna dd 1234ddh ; 4013 91a6 e800 0000 0000
dzielnik dd 10000h
iloraz dt 0.0
Wersja dla FASMa:
(przeskocz ten sam program w wersji FASMa)
; FASM:
; z wyświetlaniem:
; fasm fpu1.asm fpu1.obj
; alink fpu1.obj bibl\lib\std_bibl.lib -c- -entry _start -oEXE -m-
; bez wyświetlania:
; fasm fpu1.asm fpu1.exe
; jeśli chcesz wyświetlanie:
format coff
public _start
include "bibl\incl\fasm\std_bibl.inc"
; jeśli nie chcesz wyświetlania:
;format MZ
;entry kod:_start
;stack 400h
;segment kod
_start:
mov ax, cs
mov ds, ax
mov es, ax ; konieczne w programie typu .exe !
; %7łycie przestaje być
; wygodne. DOS już nam nie ustawi DS=ES=CS.
58 Bogdan Drozdowski
2007-11-12 Język asembler dla każdego Bogdan Drozdowski
; A nasze dane sÄ… w
; segmencie kodu, stÄ…d ustawiamy DS=CS.
; W programie typu .com to na pewno nie
; zaszkodzi.
finit ; zawsze o tym pamiętaj !!!!
fild dword [dzielna] ; Å‚adujemy dzielnÄ…. st(0) = 1234DD
fild dword [dzielnik]; Å‚adujemy dzielnik. st(0) = 10000h,
; st(1) = 1234DD
fdivp ; dzielimy. st(1) := st(1)/st(0) i
; zdejmij. st(0) ~= 18.2
fstp tword [iloraz] ; zapisujemy st(0) do pamięci i zdejmujemy
; ze stosu
; jeśli nie chcesz wyświetlania, usuń te 3 linijki niżej:
mov edi, iloraz
piszd80 ; wyświetl wynik
nwln ; przejdz do nowego wiersza
mov ax, 4c00h
int 21h
dzielna dd 1234ddh ; 4013 91a6 e800 0000 0000
dzielnik dd 10000h
iloraz dt 0.0
Ten przykład do zmiennej iloraz wstawia częstotliwość zegara komputerowego (ok. 18,2 Hz). Należy zwrócić
uwagę na zaznaczanie rozmiarów zmiennych (dword/qword/tbyte ptr).
Dyrektywa ALIGN ustawia kolejną zmienną/eytkietę tak, że jej adres dzieli się przez 8 (qword = 8 bajtów).
Dzięki temu, operacje na pamięci są szybsze (np. dla zmiennej 8-bajtowej zamiast 3 razy pobierać po 4 bajty,
bo akurat tak się zdarzyło, że miała jakiś nieparzysty adres, pobiera się 2x4 bajty). Rzecz jasna, skoro
zmienna dzielna (i dzielnik) ma 4 bajty, to adresy zmiennych dzielnik i iloraz też będą podzielne przez 4.
Ciąg cyfr po średniku to ułamkowa reprezentacja dzielnej. Skomplikowane, prawda? Dlatego nie chciałem
tego omawiać.
Przykład 2: czy sinus liczby pi rzeczywiście jest równy 0 (w komputerze)?
(przeskocz program z sinusem)
.model tiny
.code
;.386 ; odkomentować, jeżeli .387 sprawia problemy
.387
org 100h
start:
finit ; zawsze o tym pamiętaj !!!!
fldpi ; wczytujemy PI
fsin ; obliczamy sin(PI)
ftst ; porównujemy st(0) z zerem.
fstsw ax ; zapisujemy rejestr stanu bezpośrednio w AX.
; Dlatego było .387
sahf ; AH idzie do flag
[ Pobierz całość w formacie PDF ]