- Sisaldab RV32I: registreid, ABI-d ja voolu juhtimist koos e-kutsega.
- Harjutus Jupiteriga ja harjutused: negatiivne, faktorid, ahelad, rekursioon.
- Peamine risttööriistakett, käsikiri linkimine ja silumine objdumpiga.
Kui oled assembleri vastu uudishimulik ja arvad, et RISC-V on õige tee, siis oled õiges kohas. ASM-iga RISC-V-l alustamine on soodsam, kui esmapilgul tundub Kui sa mõistad tööriistu, siis mudelit programmeerimine ja mõned arhitektuuri põhireeglid.
Järgmistes ridades olen ühendanud parima mitmest allikast: harjutused Jupiteri tüüpi simulaatoritega, RV32I baasrepertuaari konventsioonid, tsüklite ja rekursioonide näiteid, süsteemikõnesid ja isegi pilk RISC-V protsessori disainile VHDL-is (ALU, mälu juhtimise ja olekumasinaga), lisaks ülevaade tööriistakettidevahelisest toimimisest ja linkimisskriptidest.
Mis on RISC-V assembler ja mille poolest see erineb masinkeelest?
Kuigi mõlemad on külge kinnitatud riistvara, Masinakeel on puhas binaarne (ühed ja nullid) mida protsessor tõlgendab otse, samas kui assembler kasutab mnemoonikat ja Sümbolid loetavam kui assembler ja seejärel teisendatakse binaarkoodiks.
RISC-V defineerib avatud ISA-d väga puhta baasrepertuaariga. RV32I (32-bitine) profiil sisaldab 39 kasutusjuhendit märkimisväärse ortogonaalsusega, eraldades mälupöörduse puhtast arvutusest ja suurepärase GCC/LLVM toega.
Dokumendid, lepingud ja sisenemispunkt
RV32I-s on sul 32 üldotstarbelist registrit (x0–x31) 32-bitine; x0 loetakse alati väärtuseks 0 ja sellele ei saa kirjutada. ABI järgimiseks on kasulikud ka varjunimed nagu a0–a7 (argumendid), t0–t6 (ajutised) või s0–s11 (salvestatud).
Sõltuvalt keskkonnast või simulaatorist võib programm alata kindla sildi juurest. Jupiteris algavad programmid globaalse __start sildiga., mille peate sisenemispunkti märkimiseks nähtavaks deklareerima (näiteks laiendiga .globl).
The sildid lõpevad kooloniga, saab rea kohta panna ainult ühe käsu ja kommentaare saab alustada sümboliga # või ;, seega assembler ignoreerib neid.
Tööriistad ja simulaatorid: Jupiter ja põhiline töövoog
Tüsistusteta harjutamiseks on teil Jupiteri simulaator/assembler, SPIM/MARS/VENUS-est inspireeritud graafiline tööriist, mis hõlbustab redigeerimist, kokkupanekut ja käivitamist ühes keskkonnas.
Jupiteris saate faile luua, redigeerida ja kustutada vahekaardil Redaktor. Pärast salvestamist koonda F3-ga ja käivita voolukäskude kaupa silumiseks, kasutades registri- ja mäluvaateid masina oleku mõistmiseks.
Programmid peavad lõppema keskkonna kutsumisega: väljumiskõne seadistusest a0 koodiga 10 (väljumine). RISC-V-s on kõned (e-call) samaväärsed süsteemikõnede või keskkonna/süsteemi suunatud lõksudega.
Programmi ja süsteemikõnede minimaalne struktuur
Akadeemilistes näidetes esinev tüüpiline struktuur määratleb alguspunkti, teeb töö ära ja lõpeb tagasikutsumisega. ecall-argumendid liiguvad tavaliselt a0–a2 intervallides ja teenuse valija a7-s, olenevalt keskkonnast.
Ühes Linux Näiteks RISC-V puhul saate printida käsuga "write syscall" ja väljuda vastava koodiga. Kirjutamiseks kasutatakse koos teenusenumbriga a0 (fd), a1 (puhver), a2 (pikkus) ja a7.Lõpuks määratakse tagastuskoodiks a0 ja väljumisnumbriks a7.
# Ejemplo mínimo (Linux RISC-V) para escribir y salir
.global _start
_start:
addi a0, x0, 1 # fd = 1 (stdout)
la a1, msg # a1 = &msg
addi a2, x0, 12 # a2 = longitud
addi a7, x0, 64 # write
ecall
addi a0, x0, 0 # return code
addi a7, x0, 93 # exit
ecall
.data
msg: .ascii "Hola mundo\n"
Kui töötate väljaspool Linuxit, näiteks hariduslikud simulaatorid oma IoT-teenusega, muutke hädaabinumbrit ja registreid vastavalt keskkonna dokumentatsioonile.
Esialgsed harjutused, mis aitavad teil kohaneda tingimuslausete, tsüklite ja mäluga
Tüüpiline soojendus on tuvastada, kas täisarv on negatiivne. Saate tagastada 0, kui see on positiivne, ja 1, kui see on negatiivne.RV32I puhul lahendab probleemi võrdlus väärtusega 0 ja „set-on-less-than” käsuga ühe läbimõeldud käsuga.
Teine väga kasulik harjutus on arvu tegurite loetlemine: liigub arvust 1 arvuni n, prindib jagajad ja tagastab, mitu neid oliHarjutate tingimuslikke hargnemisi, jagamist (või korduvat lahutamist) ning liitmise ja võrdlemisega tsükleid.
Stringidega töötamine sunnib sind mälu haldama: Külastage mälus olevat stringi iga tähemärki ja teisendage kohapeal väiketähed suurtähtedeks kui need mahuvad ASCII vahemikku. Lõpetamisel tagastab see stringi algse aadressi.
Tsüklid, funktsioonid ja rekursioon: faktoriaal, Fibonacci ja Hanoi torn
Tsüklite loomisel mõtle kolmele plokile: tingimus, keha ja samm. Beq/bne/bge ja tingimusteta hüpetega jal/j ehitatakse while/for ilma müstikata, tuginedes lisanditele ja võrdlustele.
.text
.globl __start
__start:
li t0, 0 # i
li t1, 10 # max
cond:
bge t0, t1, end # si i >= max, salta
# cuerpo: usar a0/a1 segun servicio IO del entorno
addi t0, t0, 1 # i++
j cond
end:
li a0, 10
ecall
Funktsioonikõnedes austa ABI-d: salvesta, kui kavatsed rohkem kõnesid aheldada, säilitab s0–s11 kui neid muuta, ja kasutab pinu, kus sp liigub sõna kordsetes osades.
Faktoriaal on klassikaline rekursioon: baasjuhtum n==0 tagastab 1; vastasel juhul kutsu välja factorial(n-1) ja korruta see n-ga. Kaitse ra-d ja registreid, mis enne kutsumist pinusse salvestati, ning taasta need pärast tagastamist.
factorial:
beq a0, x0, base
addi sp, sp, -8
sw ra, 4(sp)
sw s0, 0(sp)
mv s0, a0
addi a0, a0, -1
jal factorial
mul a0, a0, s0
lw s0, 0(sp)
lw ra, 4(sp)
addi sp, sp, 8
jr ra
base:
li a0, 1
jr ra
Fibonacci on kasulik mõlema harjutamiseks kahe kõnega rekursioon kui efektiivne iteratiivne versioon akumulaatormuutujatega. Ja kui soovite voo ja parameetrite juhtimise väljakutset, tõlkige lahendus assemblerisse Hanoi tornid nelja argumendiga: kettad, allikas, sihtkoht ja abitorn; see austab kutsungjärjekorda ja kuvab iga liikumise.
Mälu ligipääs, massiivid ja stringide manipuleerimine
RISC-V-s toimub mälule juurdepääs load/store käsuga: lw/sw sõnade, lh/sh poolsõnade ja lb/sb baitide jaoks, koos allkirjastatud või allkirjastamata variantidega laengutes (lb vs lbu, lh vs lhu).
Täisarvuliste massiivide läbimiseks kasutage indeksi kohta 4-baidiseid nihkeid; tekstistringide puhul liigub baithaaval edasi, kuni leiab terminaatori kui konventsioon seda nõuab (nt \0). Pidage meeles, et baasaadresse tuleb salvestada ja pointereid vastavalt vajadusele addi/auipc/la abil käsitleda.
RV32I protsessori nullist disainimine: üldine ülevaade
Kui tunned, et tahaksid räni juurde sukelduda, siis haridusprojekt loob RV32I protsessor VHDL-is, sünteesitav FPGA-s Madal-keskmine hinnaklass. Sisaldab programmi ROM-i, andme-RAM-i ja lihtsat GPIO-d LED-i süütamiseks.
Kernel rakendab baasrepertuaari (ilma M/A/C laienduste või CSR-ideta), kasutab 32-bitist aadressibussi ja võimaldab vajaduse korral 8-/16-/32-bitist märgiga laiendatud mälule juurdepääsu. Disain eraldab selgelt registrid, ALU, mälukontrolleri ja olekumasina.
ALU, vahetused ja "viivitatud laadimise" idee
ALU-d kirjeldatakse kombineeritult selliste toimingutega nagu liitmine, lahutamine, XOR, OR, AND, võrdlused (märgiga ja märgita) ja loogilised/aritmeetilised nihked.
LUT-ide salvestamiseks FPGA-s rakendatakse mitmebitiseid nihkeid olekumasina poolt juhitavate 1-bitiste nihete itereerimine: sa tarbid mitu tsüklit, aga vähendad loogilisi ressursse.
Sünkroonsetes vooluringides täheldatakse muutusi kella servadel. "Viivitatud koormuse" mõiste tuletab meelde, et multiplekseri valitud väärtus mõjutab järgmise tsükli registrit., mis on võtmetähtsusega olekumasina fetch-decode-execute kujundamisel.
Mälukontroller ja kaart: ROM, RAM ja GPIO
Mäluplokk integreerib ROM-i ja RAM-i ühtseks ruumiks, protsessori liidese lihtsustamineKontroller saab tehingute alustamiseks aadressi (AddressIn) (32 bitti), andme (DataIn), laiuse (bait/pool/sõna), märgi laiendussignaali, WE (lugemine/kirjutamine) ja käivitussignaali (Start).
Kui operatsioon on läbi, ReadyOut väärtuseks seatakse 1 ja kui see on loetud, DataOut sisaldab andmeid (nõudmisel laiendatud signiga). Kui need kirjutati, jäävad andmed muutmällu.
Näide praktilisest kaardist: ROM-ist 0x0000-st 0x0FFF-ini, GPIO bait aadressil 0x1000 (bitt 0 pinnil) ja RAM alates 0x1001 kuni 0x1FFFSelle abil saate teha vilkuri, kirjutades ja lülitades väljundbiti sisse/välja.
Registrid, multiplekserid ja olekumasinad
Protsessor defineerib 32 üldotstarbelist registrit, mis on VHDL-is massiividena eksemplarideks loodud ja millel on dekooder ALU-st kirjutamise sihtkoha valimiseks ja ülejäänu säilitamiseks.
Multiplekserid juhivad ALU sisendeid (operande ja operatsiooni), signaalid mälukontrollerile (laiused, aadress, käivitusjuhtimine ja lugemine/kirjutamine) ja spetsiaalsed registrid: PC, IR ja abiloendur iteratiivsete nihete jaoks.
Olekumasin algab reset, tõmbab arvuti poolt osutatud käsu (4-baidine lugemine), laaditakse see IR-i, kui see on valmis, ja edastatakse täitmissõlmedele: ALU (üks käsk 1 tsüklis, välja arvatud nihked), laadimine/salvestamine, hargnemised ja hüpped, lisaks erikäskudele, näiteks ebreak.
Tööriistaahelateülene linkimine ja silumine
RV32I binaarfailide genereerimiseks kasutage Rist GCC (sihtmärk riscv32-none-elf)Sa kompileerid C/C++/ASM lähtekoodid, lingid skriptiga, mis määratleb mälukaardi, ja teisendad väljundi sinu ROM/FPGA oodatud vormingusse.
Lihtne konksskript saab paigutada .text ROM-is alates 0x0000 ja .data muutmälus alates 0x1004-st (kui 0x1000–0x1003 on hõivatud GPIO registrite poolt). Käivitusrutiin võib olla „paljas“ ja paigutada pinu pointer RAM-i lõpus (nt 0x1FFC) enne peamenüüsse helistamist.
/* Mapa simple
* ROM: 0x00000000 - 0x00000FFF
* GPIO: 0x00001000 - 0x00001003
* RAM: 0x00001004 - 0x00001FFF
*/
SECTIONS {
. = 0x00000000;
.text : { *(.startup) *(.text) *(.text.*) *(.rodata*) }
. = 0x00001004;
.data : { *(.data) *(.data.*) }
}
riscv32-none-elf-objdump abil saate Võta ELF lahti ja kontrolli aadresse; näiteks näete saabas aadressil 0x00000000 koos käskudega nagu lui/addi/jal ja üleminekuga teie põhifailile. VHDL-i simulatsiooni jaoks genereerib GHDL jälgi, mida saab avada GtkWave'iga.
Pärast simulatsioonis kontrollimist vii disain FPGA-le (Quartus või muu tööriistakett). Kui RAM-i tuletatakse sisemiste plokkidena ja kood on selge RTL-vormingus, peaksite sünteesima ilma üllatusteta, isegi veteranseadmetel.
Praktilised meeldetuletused ja tüüpilised vead alustamisel
Ära seda unusta x0 on alati null; sellele kirjutamisel pole mingit efekti ja selle lugemine tagastab 0. Kasutage seda enda huvides liitmistes, võrdlustes ja registri puhastamisel.
Kui rakendate funktsioone, salvesta muudetud ra ja sN kirjedja haldab pinu sõnadega joondatud liitmiste/lahutuste abil sp-le. Naastes taastab see vastupidises järjekorras ja hüppab jr ra-ga.
Simulaatorites nagu Jupiter kontrollige, et __start on globaalne ja selle lõpetamiseks kasutage ecall'i õige (a0=10 väljumiseks). Kui midagi ei käivitu, kontrolli silti, globaalsust ja kompileeri uuesti (F3).
IO-ga harjutustes austa keskkonnaprotokolli: millised registrid kannavad parameetreid, teenuse number ja kas oodatakse aadressi või kohest väärtust. Kasutage simulaatorit või operatsioonisüsteemi dokumentatsiooni.
Selge ISA baasiga (RV32I, registrid ja ABI), mugava Jupiteri-taolise simulaatori ja kasvavate näidetega (negatiivsed väärtused, faktorid, suurtähed, tsüklid, faktoriaal, Fibonacci ja Hanoi) lakkab RISC-V assembler olemast sein ja muutub mahlakaks maastikuks protsessori mõtlemisviisi mõistmiseks. Ja kui sa julged VHDL-i peale minna, näed, kuidas ALU, mälu ja juhtimine kokku sobivad.alates käskude hankimisest ja laisast laadimisest kuni mäluliideste ja ROM-i, RAM-i ja GPIO-ga kaardini, mis võimaldab teil oma protsessoriga LED-i vilgutada.
Kirglik kirjanik baitide maailmast ja üldse tehnoloogiast. Mulle meeldib jagada oma teadmisi kirjutamise kaudu ja just seda ma selles ajaveebis teengi, näitan teile kõike kõige huvitavamat vidinate, tarkvara, riistvara, tehnoloogiliste suundumuste ja muu kohta. Minu eesmärk on aidata teil digimaailmas lihtsal ja meelelahutuslikul viisil navigeerida.