582 lines
14 KiB
NASM
582 lines
14 KiB
NASM
.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 |