604 lines
14 KiB
NASM
604 lines
14 KiB
NASM
.data
|
|
fltout: .string "Wert: %f\n"
|
|
a: .float 2.76
|
|
b: .float -3.12
|
|
c: .float 1.2
|
|
|
|
test: .string "Debug-String\n"
|
|
|
|
|
|
.text
|
|
.globl main
|
|
|
|
|
|
main:
|
|
|
|
|
|
# a * b
|
|
movl a, %eax
|
|
movl b, %ebx
|
|
call fltmul
|
|
call fltprint
|
|
|
|
|
|
|
|
# Addition läuft mit allen angegebenen Werten
|
|
|
|
# b + c
|
|
#movl b, %eax
|
|
#movl c, %ebx
|
|
#call fltadd
|
|
#call fltprint
|
|
|
|
|
|
# c + a
|
|
#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 # 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
|
|
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
|
|
|
|
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
|
|
|
|
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ührender 1 erweitern
|
|
Ein-/Ausgabe: %eax
|
|
*/
|
|
one_mantisse:
|
|
orl $0x00800000, %eax # mantisse mit führender 1 erweitern
|
|
ret
|
|
|
|
|