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

582 lines
14 KiB
NASM
Raw Blame History

.data
fltout: .string "Wert: %f\n"
a: .float 2.76
b: .float -3.12
c: .float 1.2
.text
.globl main
.globl _main
_main:
main:
# a
movl a, %eax
call fltprint
# a * b = -8,6112
movl a, %eax
movl b, %ebx
call fltmul
call fltprint
# a * c = 3,312
movl a, %eax
movl c, %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
# Exit
movl $1, %eax
int $0x80
/*
Addition zweier float Werte
Eingabe: %eax, %ebx
Ausgabe: %eax
Notizen: --AUSFUELLEN--
*/
fltadd:
pushl %eax # a 40(%esp)
pushl %ebx # b 36(%esp)
pushl $0 # 0 (sign a) 32(%esp)
pushl $0 # 0 (sign b) 28(%esp)
pushl $0 # 0 (exp a) 24(%esp)
pushl $0 # 0 (exp b) 20(%esp)
pushl $0 # 0 (mant a) 16(%esp)
pushl $0 # 0 (mant b) 12(%esp)
pushl $0 # 0 (new sign) 08(%esp)
pushl $0 # 0 (new exp) 04(%esp)
pushl $0 # 0 (new mant) 00(%esp)
# collect data
#sign a
call sign # sign of a
movl %eax, 32(%esp) # save to 32(%esp)
#sign b
movl 36(%esp), %eax # %eax = b
call sign # sign of b
movl %eax, 28(%esp) # save to 28(%esp)
#exp a
movl 40(%esp), %eax # %eax = a
call exponent # exp of a
movl %eax, 24(%esp) # save to 24(%esp)
#exp b
movl 36(%esp), %eax # %eax = b
call exponent # exp of b
movl %eax, 20(%esp) # save to 20(%esp)
#mant a
movl 40(%esp), %eax # %eax = a
call significand # mant of a
movl %eax, 16(%esp) # save to 16(%esp)
#mant b
movl 36(%esp), %eax # %eax = b
call significand # mant of b
movl %eax, 12(%esp) # save to 12(%esp)
# extend mant
#mant a
movl 16(%esp), %eax # mant of a
call one_mantisse # extend
pushl %eax # save extended mant a
#mant b
movl 16(%esp), %eax # mant of b
call one_mantisse # extend
pushl %eax # save extended mant b
#stack:
# a 48(%esp)
# b 44(%esp)
# sign a 40(%esp)
# sign b 36(%esp)
# exp a 32(%esp)
# exp b 28(%esp)
# mant a 24(%esp)
# mant b 20(%esp)
# 0 (new sign) 16(%esp)
# 0 (new exp) 12(%esp)
# 0 (new mant) 08(%esp)
# extended mant a 04(%esp) (2 be cleared)
# extended mant b 00(%esp) (2 be cleared)
# shift till exp equal
.fltadd_exp:
movl 32(%esp), %eax # exp a
movl 28(%esp), %ebx # exp b
cmp %ebx, %eax # eax = exp a - exp b ? 0
je .fltadd_exp_a_equal_b
jb .fltadd_exp_a_small_b
ja .fltadd_exp_a_great_b
.fltadd_exp_a_great_b:
movl (%esp), %ebx # ext mant b
movl 28(%esp), %ecx # exp b
shrl $1, %ebx # b >> 1
addl $1, %ecx # exp b + 1
movl %ebx, (%esp) # save change to stack (mant)
movl %ecx, 28(%esp) # save change to stack (exp)
jmp .fltadd_exp
.fltadd_exp_a_small_b:
movl 4(%esp), %ebx # ext mant a
movl 32(%esp), %ecx # exp a
shrl $1, %ebx # a >> 1
addl $1, %ecx # exp a + 1
movl %ebx, 4(%esp) # save change to stack (mant)
movl %ecx, 32(%esp) # save change to stack (exp)
jmp .fltadd_exp
.fltadd_exp_a_equal_b:
#do nothing here
# invert mant a and/or mant b if negativ
.fltadd_sign_a:
movl 40(%esp), %eax # sign a
cmp $1, %eax # a negativ?
je .fltadd_sign_a_neg
.fltadd_sign_b:
movl 36(%esp), %eax # sign b
cmp $1, %eax # b negativ?
je .fltadd_sign_b_neg
.fltadd_sign_goon:
jmp .fltadd_addmants # continue with add
.fltadd_sign_a_neg:
movl 4(%esp), %eax # ext mant a
negl %eax # invert
movl %eax, 4(%esp) # write back
jmp .fltadd_sign_b # check b
.fltadd_sign_b_neg:
movl (%esp), %eax # ext mant b
negl %eax # invert
movl %eax, (%esp) # write back
jmp .fltadd_sign_goon # continue
# add ext mants
.fltadd_addmants:
movl 4(%esp), %eax # ext signed mant a
movl (%esp), %ebx # ext signed mant b
addl %ebx, %eax # ext signed mant a + ext signed mant b
addl $8, %esp # delete ext signed mants
pushl %eax # save new combined mant (signed)
#stack:
# a 44(%esp)
# b 40(%esp)
# sign a 36(%esp)
# sign b 32(%esp)
# exp a 28(%esp)
# exp b 24(%esp)
# mant a 20(%esp)
# mant b 16(%esp)
# 0 (new sign) 12(%esp)
# 0 (new exp) 08(%esp)
# 0 (new mant) 04(%esp)
# ext mants (a+b) 00(%esp) (2 be cleared)
# calc new sign
movl (%esp), %eax # ext mants
cmp $0, %eax # ext mants ? 0
js .fltadd_newsign_neg # ext mants < 0 -> new sign -> neg
jmp fltadd_shift_strip # go on
.fltadd_newsign_neg:
movl $1, 12(%esp) # write new sign = 1 (neg)
movl (%esp), %eax # get ext mants
negl %eax # invert ext mants
movl %eax, (%esp) # write back
jmp fltadd_shift_strip #go on
# shift and strip leading one
fltadd_shift_strip:
movl 28(%esp), %eax # get exp a(=exp b)
movl (%esp), %ebx # get ext mants
fltadd_shift_loop_down: # mant bigger then possible
cmp $0x00FFFFFF , %ebx # ebx > mantspace (24 bits cuz we strip the first one)
ja fltadd_shift_loop_down_big
jmp fltadd_shift_loop_up
fltadd_shift_loop_down_big:
shrl $1, %ebx # ext mant >> 1
addl $1, %eax # exp +1
jmp fltadd_shift_loop_down
fltadd_shift_loop_up: # mant small then possible
cmp $0x00800000 , %ebx # ebx < mantspace (24 bits cuz we strip the first one)
jb fltadd_shift_loop_down_small
jmp fltadd_shift_loop_end
fltadd_shift_loop_down_small:
shll $1, %ebx # ext mant << 1
subl $1, %eax # exp -1
jmp fltadd_shift_loop_up
fltadd_shift_loop_end:
andl $0x007FFFFF, %ebx #strip 1 bit
addl $4, %esp # clear mants from stack
movl %eax, 4(%esp) # save exp
movl %ebx, (%esp) # save mants
# build new number
movl 8(%esp), %eax # new sign
movl 4(%esp), %ebx # new exp
movl (%esp), %ecx # new mant
shll $31, %eax # sign << 31 # S 0000 0000 000 0000 0000 0000 0000 0000
shll $23, %ebx # exp << 23 # 0 EEEE EEEE 000 0000 0000 0000 0000 0000
orl %ebx, %eax # S EEEE EEEE 000 0000 0000 0000 0000 0000
orl %ecx, %eax # S EEEE EEEE MMM MMMM MMMM MMMM MMMM MMMM
# clear stack
addl $44, %esp
# return
ret
/*
Multiplikation zweier float Werte
Eingabe: %eax, %ebx
Ausgabe: %eax
Notizen: --AUSFUELLEN--
*/
fltmul:
pushl %eax # a 40(%esp)
pushl %ebx # b 36(%esp)
pushl $0 # 0 (sign a) 32(%esp)
pushl $0 # 0 (sign b) 28(%esp)
pushl $0 # 0 (exp a) 24(%esp)
pushl $0 # 0 (exp b) 20(%esp)
pushl $0 # 0 (mant a) 16(%esp)
pushl $0 # 0 (mant b) 12(%esp)
pushl $0 # 0 (new sign) 08(%esp)
pushl $0 # 0 (new exp) 04(%esp)
pushl $0 # 0 (new mant) 00(%esp)
# collect data
#sign a
call sign # sign of a
movl %eax, 32(%esp) # save to 32(%esp)
#sign b
movl 36(%esp), %eax # %eax = b
call sign # sign of b
movl %eax, 28(%esp) # save to 28(%esp)
#exp a
movl 40(%esp), %eax # %eax = a
call exponent # exp of a
movl %eax, 24(%esp) # save to 24(%esp)
#exp b
movl 36(%esp), %eax # %eax = b
call exponent # exp of b
movl %eax, 20(%esp) # save to 20(%esp)
#mant a
movl 40(%esp), %eax # %eax = a
call significand # mant of a
movl %eax, 16(%esp) # save to 16(%esp)
#mant b
movl 36(%esp), %eax # %eax = b
call significand # mant of b
movl %eax, 12(%esp) # save to 12(%esp)
# extend mant
#mant a
movl 16(%esp), %eax # mant of a
call one_mantisse # extend
pushl %eax # save extended mant a
#mant b
movl 16(%esp), %eax # mant of b
call one_mantisse # extend
pushl %eax # save extended mant b
#stack:
# a 48(%esp)
# b 44(%esp)
# sign a 40(%esp)
# sign b 36(%esp)
# exp a 32(%esp)
# exp b 28(%esp)
# mant a 24(%esp)
# mant b 20(%esp)
# 0 (new sign) 16(%esp)
# 0 (new exp) 12(%esp)
# 0 (new mant) 08(%esp)
# extended mant a 04(%esp) (2 be cleared)
# extended mant b 00(%esp) (2 be cleared)
#shift mants
#mant a
movl 4(%esp), %eax # ext mant a
#movl 32(%esp), %ebx # exp a
#0000 0000 mMMM MMMM MMMM MMMM MMMM MMMM
# >>>> >>>>
shrl $8, %eax # ext mant a >> 8
#addl $8, %ebx # exp + 8
movl %eax, 4(%esp) # write back ext mant a
#movl %ebx, 32(%esp) # write back exp a
#mant b
movl (%esp), %eax # ext mant b
#movl 28(%esp), %ebx # exp b
#0000 0000 mMMM MMMM MMMM MMMM MMMM MMMM
# >>>> >>>>
shrl $8, %eax # ext mant a >> 8
#addl $8, %ebx # exp + 8
movl %eax, (%esp) # write back ext mant b
#movl %ebx, 28(%esp) # write back exp b
# multiply mants
movl 4(%esp), %eax # shifted ext mant a
movl (%esp), %ebx # shifted ext mant b
mull %ebx # shifted ext mant a * shifted ext mant b
pushl %eax # write to stack
# round fix
movl 28(%esp), %eax # mant a
andl $0x000000FF, %eax # last 8 bit
movl 4(%esp), %ebx # shifted ext mant b
mull %ebx # mul last 8 bit with b
#shrl $8, %eax # shift result >> 8 to match the other result
pushl %eax # save round-fix-result1
movl 28(%esp), %eax # mant b
andl $0x000000FF, %eax # last 8 bit
movl 12(%esp), %ebx # shifted ext mant a
mull %ebx # mul last 8 bit with b
#shrl $8, %eax # shift result >> 8 to match the other result
popl %ebx # get round-fix-result 1
addl %ebx, %eax # rf-result 1 + rf-result 2
shrl $8, %eax # shift result >> 8 to match the other result
popl %ebx # get main-result
addl %ebx, %eax # add round-fix result(1+2) + main-result
addl $8, %esp # clear stack
pushl %eax # write to stack
#stack:
# a 44(%esp)
# b 40(%esp)
# sign a 36(%esp)
# sign b 32(%esp)
# exp a 28(%esp) (altered)
# exp b 24(%esp) (altered)
# mant a 20(%esp)
# mant b 16(%esp)
# 0 (new sign) 12(%esp)
# 0 (new exp) 08(%esp)
# 0 (new mant) 04(%esp)
# multiplied mants 00(%esp) (2 be cleared)
# add exponents
movl 28(%esp), %eax # exp a
movl 24(%esp), %ebx # exp b
addl %ebx, %eax # exp a + exp b
subl $127, %eax # -1x bias
#addl $1, %eax # bit no 24
movl %eax, 8(%esp) # write to new exp
# calc sign
movl 36(%esp), %eax # sign a
movl 32(%esp), %ebx # sign b
cmp %eax, %ebx # sign a = sign b?
je fltmul_sign_eq
movl $1, 12(%esp) # if sign a != sign b -> negativ
fltmul_sign_eq:
#continue
# shift and strip leading one
fltmul_shift_strip:
movl 8(%esp), %eax # get new exp
subl $7, %eax # exp - 7 (shift before mull)
movl (%esp), %ebx # get ext mants
fltmul_shift_loop_down: # mant bigger then possible
cmp $0x00FFFFFF , %ebx # ebx > mantspace (24 bits cuz we strip the first one)
ja fltmul_shift_loop_down_big
jmp fltmul_shift_loop_up
fltmul_shift_loop_down_big:
shrl $1, %ebx # ext mant >> 1
addl $1, %eax # exp +1
jmp fltmul_shift_loop_down
fltmul_shift_loop_up: # mant small then possible
cmp $0x00800000 , %ebx # ebx < mantspace (24 bits cuz we strip the first one)
jb fltmul_shift_loop_down_small
jmp fltmul_shift_loop_end
fltmul_shift_loop_down_small:
shll $1, %ebx # ext mant << 1
#subl $1, %eax # exp -1
jmp fltmul_shift_loop_up
fltmul_shift_loop_end:
andl $0x007FFFFF, %ebx #strip 1 bit
addl $4, %esp # clear mants from stack
movl %eax, 4(%esp) # save exp
movl %ebx, (%esp) # save mants
# build new number
movl 8(%esp), %eax # new sign
movl 4(%esp), %ebx # new exp
movl (%esp), %ecx # new mant
shll $31, %eax # sign << 31 # S 0000 0000 000 0000 0000 0000 0000 0000
shll $23, %ebx # exp << 23 # 0 EEEE EEEE 000 0000 0000 0000 0000 0000
orl %ebx, %eax # S EEEE EEEE 000 0000 0000 0000 0000 0000
orl %ecx, %eax # S EEEE EEEE MMM MMMM MMMM MMMM MMMM MMMM
# clear stack
addl $44, %esp
# return
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:
andl $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
/*
Mantisse mit f<EFBFBD>hrender 1 erweitern
Ein-/Ausgabe: %eax
*/
one_mantisse:
orl $0x00800000, %eax # mantisse mit f<EFBFBD>hrender 1 erweitern
ret