Assemblyn kutsuminen C:stä
Opiskelkaa integroimaan assembly-rutiineja C/C++-projekteihin, välittämään parametreja ja vastaanottamaan paluuarvoja kutsukäytäntöjen avulla.
Assemblyn kutsuminen C:stä 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.
Miksi C tarvitsee assemblyä
Miksi C/C++- ja assembly-koodia yhdistettäisiin? Se saattaa vaikuttaa vanhanaikaiselta, mutta siihen on painavia syitä!
- Suorituskyky: Kriittisissä koodiosissa käsin optimoitu assembly voi olla kääntäjän tuottamaa koodia nopeampaa.
- Laitteiston käyttö: Voit käyttää suoraan laitteiston ominaisuuksia, joita C/C++ ei tarjoa.
- Erityiskäskyt: Voit käyttää suoraan suorittimen erityiskäskyjä (esimerkiksi salaukseen tai multimediaan).
- Vanha koodi: Voit integroida olemassa olevia assembly-rutiineja tai käyttöjärjestelmän komponentteja.
Näin saat "molempien parhaat puolet": C:n korkean tason rakenteen ja assemblyn matalan tason tehon.
Kutsusopimus
Kun C kutsuu assembly-funktiota, niiden on sovittava siitä, miten asiat toimivat. Tätä sopimusta kutsutaan kutsukäytännöksi.
Se määrittää:
- Miten argumentit välitetään (rekistereissä vai pinossa).
- Kuka siivoaa pinon kutsun jälkeen.
- Mitkä rekisterit kutsutun funktion on säilytettävä.
Moderneissa 64-bittisissä Linux- ja macOS-järjestelmissä standardi on System V AMD64 ABI. Keskitymme tähän käytäntöön.
Assemblyn julkinen rajapinta
Jotta C voi kutsua assembly-funktiota, se on määritettävä globaaliksi. Tämä kertoo linkittäjälle, että funktiota voidaan käyttää muista tiedostoista.
Perusrakenne näyttää tältä:
- Käytä
global-direktiiviä. - Määritä funktio tunnisteella (usein alaviivalla alkavalla, kuten
_my_function, vaikka System V ABI ei sitä ehdottomasti edellytä; kyseessä on yleinen käytäntö). - Lisää assembly-käskysi.
- Päätä
ret-käskyyn, joka palauttaa ohjauksen kutsujalle.
section .text
global _my_function
_my_function:
; Your assembly code here
retC:n näkökulma assemblyyn
C:n näkökulmasta assembly-funktio on aivan kuin mikä tahansa muualla määritelty funktio. Se ilmoitetaan extern-avainsanalla.
C:n funktioprototyypin on vastattava täsmälleen sitä, mitä assembly-funktio odottaa argumenttien ja palautustyypin osalta.
Jos assembly-funktiosi ottaa kaksi long-kokonaislukua ja palauttaa long-arvon, C-prototyyppi olisi esimerkiksi: extern long my_assembly_func(long a, long b);
extern long my_assembly_func(long a, long b);Datan välittäminen assemblylle
System V AMD64 ABI -käytännön mukaan kuusi ensimmäistä kokonaisluku- tai osoitinargumenttia välitetään tiettyjen rekisterien kautta:
- 1. argumentti:
RDI - 2. argumentti:
RSI - 3. argumentti:
RDX - 4. argumentti:
RCX - 5. argumentti:
R8 - 6. argumentti:
R9
Mahdolliset lisäargumentit työnnetään pinoon oikealta vasemmalle.
Tulosten palauttaminen
Kun assembly-funktiosi suoritus päättyy, se sijoittaa palautusarvon tiettyyn rekisteriin, josta C voi lukea sen.
- Kokonaisluku- tai osoitinpalautusarvoille käytetään
RAX-rekisteriä. - Liukulukuarvoille käytetään
XMM0-rekisteriä.
Sijoitettuaan tuloksen assembly-funktio suorittaa yksinkertaisesti ret-käskyn ja palaa sitä kutsuneeseen C-koodiin.
Lukujen yhteenlasku: C kutsuu assemblyä (ASM)
Luodaan assembly-funktio, joka laskee yhteen kaksi lukua. Tiedoston nimi olisi yleensä my_add.asm.
Kiinnittäkää huomiota siihen, miten argumentit vastaanotetaan rekistereissä RDI ja RSI ja miten tulos sijoitetaan rekisteriin RAX.
; my_add.asm
section .text
global add_two_numbers
add_two_numbers:
; RDI holds the first argument (a)
; RSI holds the second argument (b)
mov rax, rdi ; Move 'a' into RAX
add rax, rsi ; Add 'b' to RAX (RAX = a + b)
ret ; Return to caller (RAX holds the result)Lukujen yhteenlasku: C kutsuu assemblyä (C)
Kirjoitetaan nyt C-koodi, joka käyttää assembly-funktiotamme. Tiedoston nimi olisi yleensä main.c. Muistakaa ilmoittaa funktio extern-määreellä.
Kääntäkää ja linkittäkää näin:
nasm -f elf64 my_add.asm -o my_add.o
gcc main.c my_add.o -o my_program
./my_program
// main.c
#include <stdio.h>
// Declare the assembly function
extern long add_two_numbers(long a, long b);
int main() {
long num1 = 10;
long num2 = 25;
long sum;
// Call the assembly function
sum = add_two_numbers(num1, num2);
printf("The sum of %ld and %ld is %ld\n", num1, num2, sum);
return 0;
}Rekisterien suojaaminen
Assembly-funktiosi saattaa käyttää suorituksensa aikana useita rekistereitä. Jotkin rekisterit ovat kutsujan säilyttämiä (kutsujan on tallennettava ne, jos se tarvitsee niitä myöhemmin), kun taas toiset ovat kutsutun säilyttämiä (assembly-funktion on tallennettava ja palautettava ne, jos se muuttaa niiden arvoja).
Yleisiä kutsutun säilyttämiä rekistereitä (x64) ovat: RBX, RBP, RSP, R12, R13, R14, R15.
Jos assembly-funktiosi muuttaa kutsutun säilyttämää rekisteriä, sen arvo on tallennettava alussa PUSH-käskyllä ja palautettava ennen paluuta POP-käskyllä.
_my_function_with_preservation:
push rbx ; Save RBX
; ... use RBX ...
pop rbx ; Restore RBX
retPikatesti
Mikä rekisteri sisältäisi yleensä kolmannen C:stä assembly-funktiolle välitetyn kokonaislukuargumentin System V AMD64 ABI -käytännön mukaan?
Kertaus: C:n ja assemblyn yhdistäminen
Hienoa työtä! Olette oppineet assembly-koodin kutsumisen perusteet C:stä.
- Ymmärsitte, miksi C ja assembly kannattaa linkittää toisiinsa.
- Tutustuimme kutsukäytäntöihin ja keskityimme System V AMD64 ABI -käytäntöön.
- Näitte, miten funktioita ilmoitetaan sekä assemblyn että C:n puolella.
- Opitte, miten argumentit välitetään (rekistereissä) ja miten palautusarvot vastaanotetaan (RAX-rekisterissä).
- Tarkastelimme lyhyesti rekisterien säilyttämistä koskevia sääntöjä odottamattomien sivuvaikutusten välttämiseksi.
Tämä taito on tärkeä matalan tason optimoinnissa ja järjestelmän kanssa vuorovaikutuksessa!
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 ”Assemblyn kutsuminen C:stä” ilmainen?
Kyllä – oppitunnin ”Assemblyn kutsuminen C:stä” 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 ”Assemblyn kutsuminen C:stä”?
Opiskelkaa integroimaan assembly-rutiineja C/C++-projekteihin, välittämään parametreja ja vastaanottamaan paluuarvoja kutsukäytäntöjen avulla. 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 ”Assemblyn kutsuminen C:stä”-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
- Assemblyn kutsuminen C:stä
- C:n kutsuminen assemblysta
- Monikielisen ohjelmoinnin tekniikat
- Kutsukäytännöt: cdecl, stdcall ja System V