Sei sulla pagina 1di 12

CS220

April 18, 2007


Floating Point Instructions
• filds/fildl Loads 32 bits integer into FPU
• fists/fistl Stores top reg value to 32 bits memory
• fbld Loads BCD
• fbst Stores BCD
• fadd Floating-point addition
• fdiv Floating-point division
• fdivr Reverse floating-point division
• fmul Floating-point multiplication
• fsub Floating-point subtraction
• fsubr Reverse floating-point subtraction
• frndint Rounds the value in st(0) to the nearest int
• fsqrt Computes the square root of the value in st(0)
• fxch Exchange registers
Note: FP instructions can’t use immediate number as operand, and
can’t use one FP reg and one memory variable. You need to worry
about s/l surffix only when dealing with memory. i.e.
fadds -4(%ebp) but fadd %st(1), %st(2)
Examples
• fadds data1
– add the 32-bit value at data1 to the st(0) register
• fmull data1
– multiply the 64-bit value at data1 with the st0 register
• fidiv data1
– divide st(0) by the 32-bit integer value at data1, and store in st(0)
• fsub %st(0), %st(1)
– st(1)= st(0) - st(1) Compare: No operand:
• fsubr %st(0), %st(1) subl %eax, %ebx
%ebx=%ebx-%eax
st(0) and st(1)
– st(1)= st(1) - st(0)
• fdivs data1 One operand:
– devide the value st(0) by data1, and store in st(0) st(0) omitted
• faddp
– Add st(0) to st(1), store the result in st(1), and pop st(0)
• flds var1
flds var2
fdivp
– var2 at st(0) is divided by var1 at st(1), store in st(1) then pop, result now in st(0)
pop after operations
• fstp
• fistp After pop:

• faddp st(1) ->st(0)


st(2)->st(1)
• fsubp …
• fmulp st(0)->st(7) (invalid value, can’t be used)

• fdivp
• …
st0 3.1415926535897932385128089594061862 (raw 0x4000c90fdaa22168c235)
fld1 st1 1.10000002384185791015625 (raw 0x3fff8ccccd0000000000)
fldz st2 0 (raw 0x00000000000000000000)
st3 1 (raw 0x3fff8000000000000000)
flds var1 st4 0 (raw 0x00000000000000000000)
fldpi st5 0 (raw 0x00000000000000000000)
st6 0 (raw 0x00000000000000000000)
st7 0 (raw 0x00000000000000000000)

st0 4.2415926774316511484522185249090853 (raw 0x400187bb209110b4611a)


faddp st1 0 (raw 0x00000000000000000000)
st2 1 (raw 0x3fff8000000000000000)
st3 0 (raw 0x00000000000000000000)
st4 0 (raw 0x00000000000000000000)
st5 0 (raw 0x00000000000000000000)
st6 0 (raw 0x00000000000000000000)
invalid st7 3.1415926535897932385128089594061862 (raw 0x4000c90fdaa22168c235)

st0 6.4415927251153669687647185249090853 (raw 0x4001ce21871110b4611a)


fadds var2 st1 0 (raw 0x00000000000000000000)
st2 1 (raw 0x3fff8000000000000000)
st3 0 (raw 0x00000000000000000000)
st4 0 (raw 0x00000000000000000000)
st5 0 (raw 0x00000000000000000000)
st6 0 (raw 0x00000000000000000000)
st7 3.1415926535897932385128089594061862 (raw 0x4000c90fdaa22168c235)

fadd %st(0), %st(2) st0 6.4415927251153669687647185249090853 (raw 0x4001ce21871110b4611a)


st1 0 (raw 0x00000000000000000000)
st2 7.4415927251153669687647185249090853 (raw 0x4001ee21871110b4611a)
st3 0 (raw 0x00000000000000000000)
st4 0 (raw 0x00000000000000000000)
st5 0 (raw 0x00000000000000000000)
(var1=1.1, var2=2.2) st6 0 (raw 0x00000000000000000000)
st7 3.1415926535897932385128089594061862 (raw 0x4000c90fdaa22168c235)
.section .rodata
float add(float a,float b) .LC3:
.string "f1 + f2 = %f\n"
{
.text
return a+b; .globl main
} .type main, @function
main:
.text
pushl %ebp
.globl add movl %esp, %ebp
.type add, @function subl $8, %esp
add: movl $0x3f8ccccd, %eax
pushl %ebp movl %eax, -4(%ebp)
movl %esp, %ebp movl $0x400ccccd, %eax
movl %eax, -8(%ebp)
flds 8(%ebp)
pushl -8(%ebp)
fadds 12(%ebp) pushl -4(%ebp)
leave call add
ret addl $8, %esp
.size add, .-add subl $8, %esp # leal -8(%esp), %esp
fstpl (%esp)
pushl $.LC3
call printf
void main() addl $12, %esp
{ leave
ret
float f1=1.1f,f2=2.2f;
.size main, .-main
printf("f1 + f2 = %f\n",add(f1,f2));
}
.section .rodata
.LC3:
.string "f1 + f2 = %f\n"
double mul(double a,double b) .text
{ .globl main
return a*b; .type main, @function
} main:
pushl %ebp
.text movl %esp, %ebp
.globl mul subl $16, %esp
movl $1072798105, %edx #d1’s high part
.type mul, @function
movl $-1717986918, %eax #d1’s low part
mul: movl %edx, -4(%ebp) Little Endian:
pushl %ebp movl %eax, -8(%ebp) High part high address
movl %esp, %ebp movl $1073846681, %edx
Low part low address
fldl 8(%ebp) #a: 8(%ebp) and 12(%ebp) movl $-1717986918, %eax
movl %edx, -12(%ebp)
fmull 16(%ebp) #b: 16(%ebp) and 20(%ebp)
movl %eax, -16(%ebp)
leave Little Endian: pushl -12(%ebp)
ret pushl -16(%ebp)
Use lower 32-bit #d1’s high part
.size mul, .-mul pushl -4(%ebp)
address to access #d1’s low part
pushl -8(%ebp)
a 64 bits number
call mul
addl $16, %esp
void main() subl $8, %esp # leal -8(%esp), %esp
{ fstpl (%esp)
double d1=1.1, d2=2.2; pushl $.LC3
call printf
printf("d1 + d2 = %f\n",mul(d1,d2));
addl $12, %esp
} leave
ret
pushf
push %eax
Rounding Example finit
• Control reg 10–11 Rounding control flds value1
00 - round to nearest (default) frndint
01 - round down (toward negative fists resultnearest 4
infinity)
10 - round up (toward positive infinity) fstcw tmp
11 - round toward zero movw tmp, %ax
.section .data andw $0b1111001111111111, %ax
value1: orw $0b0000010000000000, %ax
.float 3.65 movw %ax, tmp
.section .bss fldcw tmp
.lcomm resultnearest, 4 flds value1
.lcomm resultdown, 4 frndint
.lcomm tmp, 2 fists resultdown 3
.text
.globl main popl %eax
.type main, @function popf
main: leave
pushl %ebp ret
movl %esp, %ebp .size main, .-main
Reverse Polish Notation (RPN)
• Infix notation: x * y
• RPN: x y *

• Example:
x = ((y-z)*a) - ( a + b * c )/3.14159

x = ([y z -] * a) - ( a + b * c )/3.14159
x = [y z - a *] - ( a + b * c )/3.14159
x = [y z - a *] - ( a + [b c *])/3.14159
x = [y z - a *] - [a b c * +]/3.14159
x = [y z - a *] - [a b c * + 3.14159 /]
x = [y z - a *] [a b c * + 3.14159 /] -
x = y z - a * a b c * + 3.14159 / -
((43.65 / 22) + (76.34 * 3.1)) / ((12.43 * 6) – (140.2 / 94.21))

1. Load 43.65 into st(0).


2. Divide st(0) by 22, saving the results in st(0).
3. Load 76.34 in st(0) (the answer from step 2 moves to st(1)).
4. Load 3.1 in st(0) (the value in step 3 moves to st(1), and the answer from Step 2 moves
to st(2)).
5. Multiply st(0) and st(1), leaving the answer in st(0).
6. Add st(0) and st(2), leaving the answer in st(0) (this is the left side of the equation).
7. Load 12.43 into st(0) (the answer from Step 6 moves to st(1)).
8. Multiply st(0) by 6, leaving the answer in st(0).
9. Load 140.2 into st(0) (the answer from Step 8 moves to st(1), and from Step 6 to st(2)).
10. Load 94.21 into st(0) (the answer from Step 8 moves to st(2), and from Step 6 to ST3).
11. Divide st(1) by st(0), popping the stack and saving the results in st(0) (the answer from
Step 8
12. moves to st(1), and from Step 6 to st(2)).
13. Subtract st(0) from st(1), storing the result in st(0) (this is the right side of the equation).
14. Divide st(2) by st(0), storing the result in st(0) (this is the final answer).

This example comes from recommended textbook;


it doesn’t really follow RPN notation
((43.65 / 22) + (76.34 * 3.1)) / ((12.43 * 6) – (140.2 / 94.21))
.text
.globl main
((43.65 / 22) + (76.34 * 3.1)) .type main, @function
/ main:
pushl %ebp
((12.43 * 6) – (140.2 / 94.21)) movl %esp, %ebp

finit
flds value1
.section .data
fidiv value2
value1:
flds value3
.float 43.65
flds value4
value2:
fmul %st(1), %st(0)
.int 22
fadd %st(2), %st(0)
value3:
flds value5
.float 76.34
fimul value6
value4:
flds value7
.float 3.1
flds value8
value5:
fdivrp
.float 12.43
fsubr %st(1), %st(0)
value6:
fdivr %st(2), %st(0)
.int 6
subl $8, %esp
value7:
fstpl (%esp)
.float 140.2
pushl $output
value8:
call printf
.float 94.21
add $12, %esp
output:
.string "The result is %f\n"
leave
ret
.size main, .-main

Potrebbero piacerti anche