x87 FPU -ohjelmoinnin perusteet
Oppikaa käyttämään x87-liukuluku-yksikköä (FPU) tarkkuutta vaativiin liukulukulaskuihin Assembly-kielessä.
x87 FPU -ohjelmoinnin perusteet on ilmainen Assembly-kieli ja x86-tason järjestelmäohjelmointi-oppitunti CoddyKitissä. Tämä on oppitunti 1/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Assembly-kieli ja x86-tason järjestelmäohjelmointi-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Assembly-kieli ja x86-tason järjestelmäohjelmointi-kurssilla on yhteensä 4 oppituntia.
Tutustuminen x87 FPU:hun
x87 Floating-Point Unit (FPU) on CPU:n erityinen osa, joka on suunniteltu reaalilukujen eli liukulukujen käsittelyyn.
Toisin kuin kokonaislukuaritmetiikassa, liukulukulaskennassa tarvitaan erilaisia sisäisiä esitysmuotoja ja laskutoimituksia. FPU suoriutuu niistä erittäin tarkasti.
FPU:n rekisteripino
x87 FPU käyttää yleiskäyttöisten rekisterien sijaan erityistä rekisteripinoa. Pino koostuu kahdeksasta 80-bittisestä rekisteristä, jotka on merkitty ST(0)–ST(7).
ST(0)on aina pinon päällimmäinen alkio.- Operaatiot lisäävät uusia arvoja pinoon tai poistavat arvoja pinosta siirtäen samalla olemassa olevia arvoja.
- Pino toimii periaatteella viimeisenä sisään, ensimmäisenä ulos (LIFO).
Datan lataaminen FLD:llä
Liukulukujen käsittelyä varten ne on ensin ladattava FPU:n pinoon. FLD-käsky työntää liukulukuarvon muistista FPU-pinon päälle, jolloin siitä tulee ST(0).
Assemblyssä liukulukuvakiot määritellään usein dataosiossa. Yleisiä tyyppejä ovat kertatarkkuus (32 bittiä, DD) ja kaksoistarkkuus (64 bittiä, DQ).
Kokeile ladata arvo pinoon:
section .data
float_val dq 3.1415926535
section .text
global _start
_start:
finit ; Initialize FPU
fld qword [float_val] ; Load float_val onto FPU stack (ST(0))
; At this point, ST(0) contains 3.1415926535
; We just exit as printing floats is complex in basic assembly.
mov rax, 60 ; syscall number for exit
xor rdi, rdi ; exit code 0
syscallFPU-tulosten tallentaminen
Laskutoimitusten jälkeen tulos kannattaa tallentaa FPU-pinosta takaisin muistiin. Tähän käytetään käskyjä FST ja FSTP.
FST: Kopioi arvon kohteestaST(0)muistipaikkaan tai toiseen FPU-rekisteriin ja jättää kohteenST(0)muuttumattomaksi.FSTP: Kopioi arvon kohteestaST(0)muistiin tai rekisteriin ja poistaa sen sitten pinosta pienentäen pinon osoitinta. Aiemmasta kohteestaST(1)tuleeST(0).
Tallennetaan arvo:
section .data
float_val dq 123.45
result_val dq 0.0 ; Will store result here
section .text
global _start
_start:
finit ; Initialize FPU
fld qword [float_val] ; ST(0) = 123.45
fstp qword [result_val] ; Store ST(0) to result_val, then pop.
; FPU stack is now empty.
; result_val now holds 123.45 in memory.
mov rax, 60 ; syscall number for exit
xor rdi, rdi ; exit code 0
syscallFPU:n aritmeettiset operaatiot
FPU tarjoaa käskyjä yleisiin aritmeettisiin operaatioihin. Ne toimivat yleensä kohteella ST(0) ja toisella operandilla, joka voi olla toinen pinorekisteri tai muistio-operand.
FADD: Lisää (esimerkiksiFADD ST(1), ST(0)lisääST(0):n arvon kohteeseenST(1)).FMUL: KertooFSUB: VähentääFDIV: Jakaa
FADDP ST(1), ST(0) lisää ST(0):n kohteeseen ST(1), tallentaa tuloksen kohteeseen ST(1) ja poistaa ST(0):n pinosta. Tällöin summa jää pinon päälle.
Tässä on yhteenlaskuesimerkki:
section .data
val1 dq 10.5
val2 dq 2.0
sum_result dq 0.0
section .text
global _start
_start:
finit ; Initialize FPU
fld qword [val1] ; ST(0) = 10.5
fld qword [val2] ; ST(0) = 2.0, ST(1) = 10.5
faddp st(1), st(0) ; ST(1) = ST(1) + ST(0) (10.5 + 2.0 = 12.5).
; Pop ST(0). Now ST(0) = 12.5.
fstp qword [sum_result] ; Store 12.5 to sum_result and pop.
mov rax, 60 ; syscall number for exit
xor rdi, rdi ; exit code 0
syscallFPU:n sisäiset vakiot
FPU voi ladata yleisesti käytettyjä vakioita suoraan pinoonsa, joten niitä ei tarvitse määritellä muistiin. Tämä parantaa tehokkuutta ja tarkkuutta.
FLD1: Työntää arvon 1.0 pinoon.FLDZ: Työntää arvon 0.0 pinoon.FLDPI: Työntää piin arvon (π) pinoon.
Ladataan pii:
section .data
pi_val dq 0.0 ; To store PI
section .text
global _start
_start:
finit ; Initialize FPU
fldpi ; ST(0) = PI (approx 3.14159...)
fstp qword [pi_val] ; Store PI to pi_val and pop.
mov rax, 60 ; syscall number for exit
xor rdi, rdi ; exit code 0
syscallKokonaislukujen ja liukulukujen muuntaminen
Joskus kokonaisluku- ja liukulukutyyppien välillä on muunnettava arvoja. FPU tarjoaa tähän seuraavat käskyt:
FILD(Float Integer Load): Lataa muistista etumerkillisen kokonaisluvun, muuntaa sen liukulukumuotoon ja työntää sen FPU-pinoon.FISTP(Float Integer Store and Pop): Tallentaa kohteenST(0)kokonaislukuna muistiin ja poistaa sen sitten pinosta. Muunnon aikana arvo katkaistaan kohti nollaa.
Muunnetaan kokonaisluku liukuluvuksi, lisätään arvo ja muunnetaan tulos takaisin:
section .data
int_val dd 5
float_add dq 2.5
int_result dd 0
section .text
global _start
_start:
finit ; Initialize FPU
fild dword [int_val] ; ST(0) = 5.0 (from 5)
fld qword [float_add] ; ST(0) = 2.5, ST(1) = 5.0
faddp st(1), st(0) ; ST(1) = 5.0 + 2.5 = 7.5. Pop ST(0).
; Now ST(0) = 7.5.
fistp dword [int_result] ; Store 7.5 as integer (7) to int_result and pop.
mov rax, 60 ; syscall number for exit
xor rdi, rdi ; exit code 0
syscallLiukulukujen vertaaminen
Liukulukujen vertaamiseen tarvitaan erityisiä FPU-käskyjä. Kokonaislukujen vertailukäskyjä, kuten CMP, ei voi käyttää suoraan.
FCOM: Vertaa kohdettaST(0)operandiin, joka voi olla toinen FPU-rekisteri tai muistipaikka, ja asettaa FPU:n tilaliput.FCOMP: Toimii kutenFCOM, mutta poistaa kohteenST(0)vertailun jälkeen.
Jotta näitä lippuja voidaan käyttää ehdollisiin hyppäyksiin, kuten JE ja JB, ne on siirrettävä FPU:n tilasanasta CPU:n EFLAGS-rekisteriin:
FSTSW AX: Tallentaa FPU:n tilasanan rekisteriinAX.SAHF: Siirtää rekisterinAH, joka sisältää nyt tarvittavat FPU:n liput, CPU:nEFLAGS-rekisteriin, erityisesti liputZF,PFjaCF.
Kootaan kokonaisuus: (A + B) * C
Yhdistetään oppimamme ja suoritetaan yksinkertainen laskutoimitus: (A + B) * C. Ladataan kolme arvoa, lasketaan kaksi niistä yhteen, kerrotaan summa kolmannella ja tallennetaan lopullinen kokonaislukutulos.
Tämä esimerkki havainnollistaa pinon käsittelyä ja aritmeettisia operaatioita.
section .data
val_A dq 3.0
val_B dq 1.5
val_C dq 2.0
final_int_result dd 0
section .text
global _start
_start:
finit ; Initialize FPU
fld qword [val_A] ; ST(0) = 3.0
fld qword [val_B] ; ST(0) = 1.5, ST(1) = 3.0
faddp st(1), st(0) ; Add ST(0) (1.5) to ST(1) (3.0), store in ST(1).
; Pop ST(0). Now ST(0) = 4.5 (sum of A+B)
fld qword [val_C] ; ST(0) = 2.0, ST(1) = 4.5 (A+B)
fmulp st(1), st(0) ; Multiply ST(0) (2.0) by ST(1) (4.5), store in ST(1).
; Pop ST(0). Now ST(0) = 9.0 ((A+B)*C)
fistp dword [final_int_result] ; Store 9.0 as integer (9) to final_int_result and pop.
mov rax, 60 ; syscall number for exit
xor rdi, rdi ; exit code 0
syscallFPU-pinon haaste
Tarkastele seuraavaa x87 FPU:n assembly-koodikatkelmaa. Mikä on kohteen ST(0) arvo sen suorittamisen jälkeen?
section .data
val_X dq 10.0
val_Y dq 3.0
section .text
finit
fld qword [val_X] ; ST(0) = 10.0
fld qword [val_Y] ; ST(0) = 3.0, ST(1) = 10.0
faddp st(1), st(0) ; ST(0) = 13.0
fld1 ; ST(0) = 1.0, ST(1) = 13.0
fsub ; ST(0) = ST(0) - ST(1) (1.0 - 13.0 = -12.0)x87 FPU:n yhteenveto
Olet ottanut ensimmäiset askeleesi x87 FPU -ohjelmoinnissa! Käsittelimme seuraavat asiat:
- FPU:n kahdeksan rekisterin pinon (
ST(0)–ST(7)). - Arvojen lataamisen komennolla
FLDja tallentamisen komennoillaFST/FSTP. - Perusaritmetiikan:
FADD,FSUB,FMULjaFDIV. - Sisäisten vakioiden, kuten
FLD1,FLDZjaFLDPI, käytön. - Kokonaislukujen ja liukulukujen muuntamisen komennoilla
FILDjaFISTP. - FPU-vertailujen tulosten valmistelemisen ehdollisia hyppäyksiä varten.
x87 FPU soveltuu tarkkoihin laskutoimituksiin, vaikka nykyaikaisissa järjestelmissä käytetään usein nopeampia SIMD-laajennoksia, kuten SSE:tä ja AVX:ää. Niihin tutustut seuraavaksi!
Opi Assembly tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 12
- Oppitunnit
- 48
Usein kysytyt kysymykset
Onko oppitunti ”x87 FPU -ohjelmoinnin perusteet” ilmainen?
Kyllä – oppitunnin ”x87 FPU -ohjelmoinnin perusteet” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Assembly-kieli ja x86-tason järjestelmäohjelmointi-kurssin, päivitä CoddyKit PROhon. Assembly-kieli ja x86-tason järjestelmäohjelmointi-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”x87 FPU -ohjelmoinnin perusteet”?
Oppikaa käyttämään x87-liukuluku-yksikköä (FPU) tarkkuutta vaativiin liukulukulaskuihin Assembly-kielessä. Harjoittelet Assembly-kieli ja x86-tason järjestelmäohjelmointi-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Assembly-kieli ja x86-tason järjestelmäohjelmointi-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Assembly-kieli ja x86-tason järjestelmäohjelmointi-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 1/4.
Kuinka kauan ”x87 FPU -ohjelmoinnin perusteet”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Assembly-kieli ja x86-tason järjestelmäohjelmointi-oppitunnilla?
Kyllä. Jokainen Assembly-kieli ja x86-tason järjestelmäohjelmointi-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- x87 FPU -ohjelmoinnin perusteet
- SSE/AVX-käskyvalikoimien johdanto
- Koodin vektorointi SIMD:n avulla
- Liukulukujen tarkkuus, pyöristys ja poikkeukset