college/ws2010/gdi3/solution/u5/floatingStripped_ulf.asm
2013-12-19 22:22:57 +01:00

529 lines
11 KiB
NASM

.data
fltout: .string "Wert: %f\n"
intout: .string "Wert: %d\n"
a: .float 2.76
b: .float -3.12
c: .float 1.2
.text
#Windebugging
.globl _main
.globl main
#.global printf
#printf:
# call _printf
# ret
_main:
jmp main
main:
#float 2 console
movl a, %eax
call fltprint
# a * b = -8,6112
#movl a, %eax
#movl b, %ebx
#call fltmul
#call fltprint
# b + c = -1,92
movl b, %eax
movl c, %ebx
call fltadd
call fltprint
# c + a = 3,96
#movl c, %eax
#movl a, %ebx
#call fltadd
#call fltprint
.ende:
# Exit
movl $1, %eax
int $0x80
################################################################################################################################
/*
Addition zweier float Werte
Eingabe: %eax, %ebx
Ausgabe: %eax
Notizen: --AUSFUELLEN--
*/
fltadd:
pushl %eax
pushl %ebx
# VERGLEICHE EXPONENTEN -> SHIFTE MANTISSE ENTSPRECHEND
##################################################################################
call exponent # liefert exponent von %eax in %eax #lieft null -> für 3.... -> 11...., also müsste exponent mind 1 sein
pushl %eax # movl %eax, %edx # a
# b
# exp a
movl 4(%esp), %eax # movl %ebx, %eax # verschieben b in %eax
call exponent # liefert exponent von %ebx in %eax #ist null und richtig
pushl %eax # # a
# b
# exp a
# exp b
movl %eax, %ebx # Eponent von %ebx in %ebx
movl 4(%esp), %eax # Exponent von %eax in %eax
cmp %ebx, %eax # vergleiche exponenten
jb .shift_eax # %ebx ist größer -> shift eax
ja .shift_ebx # %ebx ist kleiner -> shift ebx
je .shift_nothing # exponenten gleich, kein shift notwendig
.shift_eax:
#TODO
pushl %ebp
movl %esp, %ebp
pushl %ebx # Exponent sichern
subl %ebx, %eax # %eax - %ebx
pushl %eax # Shiftwert sichern
movl 4(%ebp), %ebx # Urpsüngliche Gleitkommazahl herstellen
movl 8(%ebp), %eax
call significand # liefert Mantisse von %eax
popl %ecx
.loop_shift: # Shifte Mantisse von %eax x-mal
shrl $1, %eax
loop .loop_shift
pushl %eax
movl %ebx, %eax
call significand # Extrahiere Mantisse von %ebx
movl %eax, %ebx
popl %eax
popl %edx # Exponent wiederherstellen
jmp .add_fraction
popl %ebp
jmp .shift_nothing
.shift_ebx:
subl %ebx, %eax # %eax - %ebx
pushl %eax # Shiftwert sichern # a
# b
# exp a
# exp b
# shift b
movl 12(%esp), %eax # Urpsüngliche Gleitkommazahl herstellen (b)
call significand # liefert Mantisse von b
popl %ecx
.loop_shift2: # Shifte Mantisse von %eax x-mal um 2 nach LINKS
shll $1, %eax
loop .loop_shift2
pushl %eax # a
# b
# exp a
# exp b
# mantisse b
movl 16(%esp), %eax
call significand # Extrahiere Mantisse von a
pushl %eax # a
# b
# exp a
# exp b
# mantisse b
# mantisse a
jmp .check_sign
.shift_nothing: # %eax und %ebx haben gleichen Exponenten!
movl 8(%esp), %eax
call significand # Extrahiere Mantisse von b
pushl %eax
movl 16(%esp), %eax
call significand # Extrahiere Mantisse von a
pushl %eax
#######################################################################################
;# VERGLEICHE VORZEICHEN UND BILDE EVENTUELL ZWEIERKOMPLEMENT
#######################################################################################
.check_sign:
# a
# b
# exp a
# exp b
# mantisse b
# mantisse a
movl 20(%esp), %eax # Urpsüngliche Gleitkommazahl herstellen (a)
call sign # Vorzeichen von %eax extrahieren (a)
cmp $1, %eax
je .build_complement_a # Zweier Komplement bilden
.sign_b:
movl 16(%esp), %eax # Urpsüngliche Gleitkommazahl herstellen (b)
call sign # Vorzeichen von %eax extrahieren (b)
cmp $1, %eax
je .build_complement_b # Zweier Komplement bilden
jmp .sign_end
.build_complement_a:
movl (%esp), %eax # Hole Mantisse von a
xor $0x007FFFF, %eax # Invertiere %eax 0000 0000 07 F F F F F
inc %eax # %eax +1
movl %eax, (%esp) # Schriebe Mantisse zurück
jmp .sign_b
.build_complement_b:
movl 4(%esp), %eax # Hole Mantisse von b
xor $0x007FFFF, %eax # Invertiere %eax
inc %eax # %eax + 1
movl %eax, 4(%esp) # Schreibe Mantisse zurück
jmp .sign_end
.sign_end:
#######################################################################################
;# ADDIERE MANTISSEN
#######################################################################################
.add_fraction:
# a
# b
# exp a
# exp b
# mantisse b
# mantisse a
movl (%esp), %eax # mantisse a
movl 4(%esp), %ebx # mantisse b
addl %ebx, %eax # Mantissen addieren
pushl %eax # %eax sichern # a
# b
# exp a
# exp b
# mantisse b
# mantisse a
# new mantisse
movl 16(%esp), %eax # exp a
movl 12(%esp), %ebx # exp b
subl %ebx, %eax # exp a - exp b
cmp $0, %eax # exp a - exp b = 0?
je .exp_eql
ja .exp_a_big
jb .exp_b_big
.exp_eql:
movl 16(%esp), %eax # exp a
pushl %eax
movl 28(%esp), %eax # a
call sign
pushl %eax
# a
# b
# exp a
# exp b
# mantisse b
# mantisse a
# new mantisse
# new exp
# new sign
jmp .build_flt
.exp_a_big:
movl 16(%esp), %eax # exp a
pushl %eax
movl 28(%esp), %eax # a
call sign
pushl %eax
# a
# b
# exp a
# exp b
# mantisse b
# mantisse a
# new mantisse
# new exp
# new sign
jmp .build_flt
.exp_b_big:
movl 12(%esp), %eax # exp b
pushl %eax
movl 24(%esp), %eax # b
call sign
pushl %eax
# a
# b
# exp a
# exp b
# mantisse b
# mantisse a
# new mantisse
# new exp
# new sign
jmp .build_flt
.build_flt:
movl (%esp), %eax # sign << 31
movl 4(%esp), %ebx # exp << 23
movl 8(%esp), %ecx # mantisse << 0
shll $31, %eax # ok!
shll $23, %ebx # ok!
orl %ebx, %eax
orl %ecx, %eax
addl $36, %esp
#??????????????????????????????ß
#andl $0x00800000, %eax # prüfe ob shift und Exponentanpassung nötig ist
#shrl $23, %eax
#cmp $0, %eax
#je .no_shift
#popl %eax
#shrl $1, %eax
#inc %edx
#.no_shift:
## Vorzeichenbit muss noch behandelt werden
# cmp $0, %eax # ergebnis < 0 -> Zweierkomplement bilden
# ja .no_complement
#
# # Zweierkomplement vom Ergebnis bilden
# xor $0x00711111, %eax
# inc %eax
# xor $0x80000000, %eax # -> Vorzeichenbit setzen
#
# .no_complement:
#
# # Zahl wieder "zusammenbauen"
# subl $896, %edx # Exponent wieder in richtige Form bringen
# andl 0x7F800000, %edx
# orl %edx, %eax # Exponent_Mantisse
#######################################################################################
ret
################################################################################################################################
################################################################################################################################
/*
Multiplikation zweier float Werte
Eingabe: %eax, %ebx
Ausgabe: %eax
Notizen: --AUSFUELLEN--
*/
fltmul:
pushl %eax
pushl %ebx
call significand # Mantisse von %eax bestimmen
orl 0x00100000, %eax
pushl %eax
movl %ebx, %eax # Mantisse von %ebx bestimmen
call significand
orl 0x00100000, %eax
movl %eax, %ebx
popl %eax
# 2 * 24 bit = 48 bit !!!!
mull %ebx # Mantissen multiplizieren
pushl %eax # Sichere neue Mantissse auf dem Stack
movl 4(%ebp), %ebx # ebx wieder herstellen
movl 8(%ebp), %eax # eax wieder herstellen
#Expoenten extrahieren und neuen Exponent bestimmen
call exponent
pushl %eax
movl %ebx, %eax
call exponent
movl %eax, %ebx
popl %eax
addl %ebx, %eax # Addiere beide Exponenten
subl $127, %eax # Exponenten - (1 x BIAS)
pushl %eax # Sichere neuen Exponentn auf dem Stack
#Berechne Vorzeichen des Produkts
movl 4(%ebp), %ebx # ebx wieder herstellen
movl 8(%ebp), %eax # eax wieder herstellen
call sign
movl %eax, %ebx
pushl %eax
movl %ebx, %eax
call sign
movl %eax, %ebx
popl %eax
xor %ebx, %eax
pushl %eax # Neuen Exponent auf Stack sichern
# Ergebnis zusammensetzen
ret
################################################################################################################################
/*
Ausgabe einer float Zahl via printf
Wichtig: printf ist leider nur double kompatibel,
daher muss float auf double erweitert werden
auch wenn %f genutzt wird!
Eingabe: %eax
Ausgabe: ---
*/
fltprint:
pusha
call extend # Wegen printf auf double erweitern
pushl %edx
pushl %eax
pushl $fltout
call _printf
addl $12, %esp
popa
ret
/*
Erweitert ein float in double
Eingabe: %eax
Ausgabe: %edx:%eax
Notizen: %ebx enthaelt dauerhaft den float-Wert
; %ecx:%edx Zwischenergebniss der Erweiterung
; %edx enthaelt Differenz der Exponenten
*/
extend:
pushl %ebx
pushl %ecx
movl %eax, %ebx # Sicherung des floats
call sign # Vorzeichen extrahieren
movl %eax, %ecx # ecx:edx wird double enthalten
movl %ebx, %eax
call exponent # Exponent extrahieren
addl $896, %eax # Exponent erweitern -127 +1023
shll $11, %ecx
orl %eax, %ecx # An ecx anhaengen
movl %ebx, %eax
call significand # Mantisse extrahieren
movl %eax, %edx
shrl $3, %eax # Nur 20 Bit passen noch dran
shll $20, %ecx
orl %eax, %ecx
shll $29, %edx # Mantisse erweitern
movl %edx, %eax # Ausgabe setzen
movl %ecx, %edx
popl %ecx
popl %ebx
ret
/*
Vorzeichen des floats extrahieren
Ein-/Ausgabe: %eax
Notizen: --AUSFUELLEN--
*/
sign:
shrl $31, %eax # %eax shiften
ret
/*
Exponent des floats extrahieren
Ein-/Ausgabe: %eax
Notizen: --AUSFUELLEN--
*/
exponent:
and $0x7F800000, %eax # exponent maskieren
shrl $23, %eax # %eax shiften
ret
/*
Mantisse des floats extrahieren
Ein-/Ausgabe: %eax
Notizen: --AUSFUELLEN--
*/
significand:
andl $0x007FFFFF, %eax # mantisse maskieren
ret