Kas yra taikomoji dvejetainė sąsaja (ABI)?

Aš niekada nesupratau, kas yra ABI. Prašome neduoti man straipsnio apie Vikipediją. Jei galėčiau tai suprasti, negalėčiau paskelbti tokios ilgos žinutės.

Tai mano mąstymas apie skirtingas sąsajas:

Televizoriaus nuotolinio valdymo pultas yra vartotojo ir televizoriaus sąsaja. Tai esamas subjektas, bet nenaudingas (nesuteikia jokių funkcijų). Visi nuotolinio valdymo pulto mygtukai yra įdiegti televizoriuje.

Sąsaja :. Tai yra „esamo objekto“ sluoksnis tarp šios functionality ir consumer . Pati sąsaja nieko nedaro. Tai tik sukelia funkciją už jos.

Dabar, priklausomai nuo to, kas yra vartotojas, tai yra skirtingų tipų sąsajos.

Komandinės eilutės komandos (CLI) yra esami subjektai, vartotojas yra vartotojas, o funkcionalumas atsilieka.

functionality: mano programinės įrangos funkcionalumas, kuris išsprendžia tam tikrą tikslą, kurį aprašome šioje sąsajoje.

existing entities: komandos

consumer: vartotojas

Grafinė vartotojo sąsaja (GUI) , mygtukai ir kt. - tai yra esami objektai, o vartotojas yra vartotojas, o funkcionalumas atsilieka.

functionality: mano programinės įrangos funkcionalumas, kuris išsprendžia tam tikrą tikslą, kurį aprašome šioje sąsajoje.

existing entities: >

consumer: vartotojas

Programos sąsaja (API) arba teisingesnė, sąsajos (konjuguoto programavimo srityje) yra esami subjektai, vartotojas yra kita programa, o ne vartotojas, ir vėl funkcionalumas yra už šio sluoksnio.

functionality: mano programinės įrangos funkcionalumas, kuris išsprendžia tam tikrą tikslą, kurį aprašome šioje sąsajoje.

existing entities: funkcijos, sąsajos (funkcijų masyvas).

consumer: kita programa / programa.

Dvejetainė taikymo sąsaja (ABI) Čia prasideda mano problema.

functionality:

existing entities:

consumer:

  • Aš parašiau programinę įrangą skirtingomis kalbomis ir pateikiau skirtingas sąsajas (CLI, GUI ir API), bet nesu įsitikinęs, ar kada nors pateikiau ABI.

Wikipedia sako:

ABI apima tokias detales kaip

  • duomenų tipas, dydis ir derinimas;
  • skambinančioji konvencija, kuri nustato, kaip perduodami funkcijų argumentai ir grąžinamos grąžinamos vertės;
  • sistemos skambučių numeriai ir kaip programa turėtų skambinti į operacinę sistemą;

Kiti ABI standartizuoja tokius duomenis kaip

  • C ++ raktinio žodžio pavadinimas,
  • išimčių skleidimas ir. \ t
  • sudaryti susitarimą tarp kompiliatorių toje pačioje platformoje, tačiau nereikalauja suderinamumo tarp platformų.
  • Kam reikalingi šie duomenys? Nepasakykite OS. Aš žinau surinkimo programavimą. Žinau, kaip veikia nuorodos ir atsisiuntimai. Žinau, kas tiksliai vyksta viduje.

  • Kodėl atsirado pavadinimas C ++? Maniau, kad kalbame dvejetainiu lygmeniu. Kodėl rodomos kalbos?

Bet kuriuo atveju, aš atsisiunčiau [PDF] „System V Application Binary Interface Edition“ 4.1 (1997-03-18), kad sužinotumėte, kas tiksliai yra. Na, dauguma jų neturi prasmės.

  • Kodėl jame yra du skyriai (4 ir 5), kuriuose aprašomas ELF failo formatas? Tiesą sakant, tai tik du svarbūs šios specifikacijos skyriai. Likę skyriai yra „procesoriaus specifiniai“. Bet kokiu atveju, aš maniau, kad tai visiškai kita tema. Nesakykite, kad ELF failo formato specifikacija yra ABI. Tai negali būti sąsaja, kaip apibrėžta.

  • Žinau, nes kalbame tokiu mažu lygiu, jis turi būti labai konkretus. Bet aš nesu įsitikinęs, kaip tai yra specifinė instrukcijų rinkinio architektūra (ISA)?

  • Kur galiu rasti „Microsoft Windows ABI“?

Taigi, tai yra pagrindiniai prašymai, kurie mane klaidina.

274
31 янв. nagai nustatyti sausio 31 d 2010-01-31 12:30 '10, 12:30, 2010-01-31 12:30
@ 13 atsakymų

Vienas paprastas būdas suprasti „ABI“ yra palyginti jį su „API“.

Jūs jau esate susipažinę su API sąvoka. Jei norite naudoti, pvz., Bet kurios bibliotekos ar operacinės sistemos funkcijas, naudosite API. API susideda iš duomenų tipų / struktūrų, konstantų, funkcijų ir tt, kuriuos galite naudoti savo kode, kad galėtumėte pasiekti šios išorės komponento funkcijas.

ABI yra labai panašus. Pagalvokite apie tai kaip sukurtą API versiją (arba kaip API kalbos kalbos lygmeniu). Rašydami šaltinio kodą, jūs gaunate prieigą prie bibliotekos, nors ir API. Sukūrę kodą, jūsų programa pasiekia bibliotekoje esančius dvejetainius duomenis per ABI. ABI apibrėžia struktūras ir metodus, kuriuos jūsų sukaupta programa naudos, norėdama pasiekti išorinę biblioteką (kaip API), tik žemesniame lygyje.

ABI yra svarbios, kai kalbama apie programas, kuriose naudojamos išorinės bibliotekos. Jei sukurta programa, skirta naudoti tam tikrą biblioteką, o ši biblioteka vėliau atnaujinama, nenorite perskaičiuoti šios programos (ir galutinis vartotojas gali neturėti šaltinio). Jei atnaujintoje bibliotekoje naudojama ta pati ABI, jūsų programa nereikia keisti. Sąsaja su biblioteka (kurią visos jūsų programos tikrai rūpinasi) yra tokia pati, nors vidinis darbas gali būti pakeistas. Dvi bibliotekos versijos, turinčios tą patį ABI, kartais vadinamos „dvejetainiu suderinamumu“, nes jos turi tą pačią žemo lygio sąsają (turėtumėte turėti galimybę pakeisti seną versiją nauja ir neturėti rimtų problemų).

Kartais ABI pokyčiai yra neišvengiami. Tokiu atveju visos programos, kurios naudoja šią biblioteką, neveiks, jei nebus sukompiliuotos naudoti naują bibliotekos versiją. Jei pasikeičia ABI, bet API nėra, senosios ir naujos versijos bibliotekoje kartais vadinamos „suderinama su šaltinio kodu“. Tai reiškia, kad nors viena bibliotekos versija sukompiliuota programa neveiks su kitu, šaltinio kodas, parašytas vienam, dirbs kitam, jei jis bus sudarytas.

Dėl šios priežasties bibliotekų kūrėjai linkę išlaikyti savo ABI stabilumą (kad sumažintų sutrikimus). ABI stabilumo palaikymas reiškia, kad nekeičiamos funkcinės sąsajos (grąžinamų duomenų tipas ir skaičius, argumentų tipas ir tvarka), duomenų tipų apibrėžimas arba duomenų struktūra, tam tikros konstantos ir kt. Galima pridėti naujų funkcijų ir duomenų tipų, tačiau esami turėtų likti tie patys. Jei 32 bitų lauke naudosite, pvz., 16 bitų duomenų struktūros lauką, tada jau sukompiliuotas kodas, kuris naudoja šią duomenų struktūrą, teisingai nenurodys šio lauko (arba bet kurio kito). Prieiga prie duomenų struktūros elementų konvertuojama į adresus ir atminties kompensacijas kompiliavimo metu, o jei duomenų struktūra pasikeičia, šie kompensavimai neparodo, kad kodas tikisi, kad jie nurodys, o rezultatai geriausiu atveju nenuspėjami.

ABI nebūtinai yra tai, ką aiškiai nurodote, jei nenorite, kad žmonės sąveikauja su jūsų kodu, naudodami surinkimą. Tai nepriklausoma nuo kalbos, nes (pvz.) Programa C ir Pascal taikys tą patį ABI po jų sudarymo.

Redagavimas: Dėl jūsų klausimų apie skyrių apie ELF failo formatą SysV ABI dokumentuose: priežastis, dėl kurios ši informacija yra įtraukta, yra tai, kad ELF formatas apibrėžia operacinės sistemos ir programos sąsają. Kai pasakysite OS, kad paleistumėte programą, ji tikisi, kad programa bus suformatuota tam tikru būdu ir (pavyzdžiui) tikisi, kad pirmoji dvejetainio failo dalis bus ELF antraštė, kurioje yra tam tikra informacija tam tikruose atminties poslinkiuose. Taip programa perduoda svarbią informaciją apie save operacinei sistemai. Jei sukuriate kitą dvejetainį programą nei ELF (pvz., A.out arba PE), tuomet programoje, laukiančioje ELF formatuotų programų, OS negalės interpretuoti dvejetainio failo arba paleisti programą. Tai yra viena iš pagrindinių priežasčių, kodėl „Windows“ programos negali paleisti tiesiai ant „Linux“ įrenginio (arba atvirkščiai), nekompiliuojant ar vykdant tam tikrą emuliacijos sluoksnį, kuris gali išversti iš vieno dvejetainio formato į kitą.

IIRC, „Windows“ šiuo metu naudoja „ Portable Executable“ (arba PE). Šio „Vikipedijos“ puslapio skiltyje „Išorės nuorodos“ yra nuorodų su papildoma informacija apie PE formatą.

Be to, atsižvelgiant į jūsų pastabą dėl C ++ vardo pažinimo: ABI gali apibrėžti „standartizuotą“ būdą C ++ kompiliatoriui, kad jis galėtų tvarkyti pavadinimą, kad būtų užtikrintas suderinamumas. Tai reiškia, kad jei sukursiu biblioteką ir kuriate programą, kuri naudoja biblioteką, turėtumėte turėti galimybę naudoti kitą kompiliatorių, nei aš, ir jums nereikia nerimauti dėl to, kad atsirandantys dvejetainiai nesuderinami dėl skirtingų pavadinimų perjungimo schemų. Tai tikrai naudinga, jei apibrėžiate naują dvejetainį failo formatą arba rašote kompiliatorių arba nuorodą.

304
16 марта '10 в 21:04 2010-03-16 21:04 Atsakymą duoda „ bta “ kovo 16 d., 10 val. , 04:04 2010-03-16 21:04

Jei žinote, kaip veikia ir kaip viskas veikia OS lygiu, jūs atitinkate tam tikrą ABI. ABI valdo tokius dalykus, kaip parametrai yra perduodami, kur grąžinimo reikšmės yra pateikiamos. Daugelyje platformų yra tik viena ABI, ir tokiais atvejais ABI yra tiesiog „kaip tai veikia“.

Tačiau ABI taip pat valdo tokius dalykus, kaip, pavyzdžiui, klasių / objektų išdėstymas C + +. Tai būtina, jei norite, kad būtų galima perduoti nuorodas į objektus per modulio ribas arba jei norite sumaišyti kodą, sudarytą su skirtingais kompiliatoriais.

Be to, jei turite 64 bitų operacinę sistemą, kuri gali vykdyti 32 bitų binarus, turėsite skirtingus ABI 32 ir 64 bitų kodui.

Apskritai bet koks kodas, kurį susieti su tuo pačiu vykdomuoju failu, turi atitikti tą patį ABI. Jei norite bendrauti tarp kodo naudojant skirtingus ABI, turite naudoti tam tikrą RPC arba serializacijos protokolų formą.

Manau, kad bandote pernelyg sunkiai suspausti įvairių tipų sąsajas į fiksuotą charakteristikų rinkinį. Pavyzdžiui, sąsaja neturi būti suskirstyta į vartotojus ir gamintojus. Sąsaja yra tiesiog konvencija, kuria du objektai sąveikauja.

border=0

ABI gali būti (iš dalies) ISA agnostikas. Kai kurie aspektai (pvz., Skambinimo sutartys) priklauso nuo ISA, o kiti aspektai (pvz., C ++ klasės išdėstymas) neveikia.

Gerai apibrėžtas ABI yra labai svarbus žmonėms, rašantiems kompiliatorius. Be aiškiai apibrėžtos ABI, būtų neįmanoma sukurti sąveikaus kodo.

Redaguoti: kai kurios pastabos paaiškinimui:

  • „Binarinė“ ABI nepanaikina styginių ar teksto naudojimo. Jei norite susieti DLL, kuris eksportuoja C + klasės klasę, metodai ir parašų tipai turi būti koduojami kažkur. Tai atsitinka su pavadinimu C ++.
  • Priežastis, dėl kurios niekada nepateikėte ABI, yra tai, kad didžioji dauguma programuotojų niekada to nepadarys. ABI sukuria tie patys žmonės, kurie kuria platformą (ty operacinę sistemą), ir labai nedaug programuotojų turės teisę sukurti plačiai naudojamą ABI.
83
31 янв. Atsakymą pateikė JesperE sausio 31 d. 2010-01-31 12:50 '10, 12:50, 2010-01-31 12:50

Dvejetainė taikomoji sąsaja (ABI) yra panaši į API, tačiau ši funkcija nėra prieinama skambinančiajam šaltinio kodo lygiu. Galimas / tik galimas dvejetainis vaizdas.

ABI gali būti apibrėžti procesoriaus architektūros lygiu arba OS lygiu. ABI yra standartai, kurių turi laikytis kompiliatoriaus kodo generavimo fazė. Standartą nustato arba operacinė sistema, arba procesorius.

Funkcionalumas: nustatykite mechanizmą / standartą, kad būtų galima skambinti funkcijoms nepriklausomai nuo diegimo kalbos ar konkrečios kompiliatoriaus / sąsajos / įrankių grandinės. Pateikite mechanizmą, leidžiantį JNI, arba Python-C sąsają ir tt

Esami objektai: veikia kaip mašinos kodas.

Vartotojas: kita funkcija (įskaitant kitą kalbą, kurią parengia kitas kompiliatorius arba susietas su kitu sąsaju).

14
23 марта '10 в 9:07 2010-03-23 09:07 atsakymą pateikė alvin, kovo 23 d., 10 d., 09:07 2010-03-23 ​​09:07

Funkcionalumas: sutarčių rinkinys, turintis įtakos kompiliatoriui, kolekcininkams, sąsajai ir operacinei sistemai. Sutartyse nustatoma, kaip paskirstomos funkcijos, kur perduodami parametrai, kaip perduodami parametrai, kaip funkcija grąžinama. Paprastai jie yra būdingi rinkiniams (procesoriaus architektūra, operacinė sistema).

Esami objektai: parametrų vieta, funkcijų semantika, registrų paskirstymas. Pavyzdžiui, ARM architektūrose yra daug ABI (APCS, EABI, GNU-EABI, nesvarbu, kiek istorinių atvejų) - naudojant mišrią ABI kodą jūsų kodas paprasčiausiai neveiks, kai skambinsite per sienas.

Vartotojų: kompiliatorius, montuotojai, operacinė sistema, procesoriaus architektūra.

Kam reikalinga ši informacija? Kompiliatorius, kolekcionieriai, jungikliai, kurie generuoja kodą (arba derinimo reikalavimus), operacinė sistema (pertraukimo valdymas, syscall sąsaja). Jei programavote statybą, buvote ABI suderinamas!

„C ++“ pavadinimo susiliejimas yra ypatingas atvejis - jo problema su „linker“ ir dinaminiu „linker“ - jei vardų valdymas nėra standartizuotas, dinaminis išdėstymas neveiks. Toliau C ++ ABI tai vadinama, C ++ ABI. Tai nėra „linker“ problema, bet kodų generavimo problema. Kai turėsite C + + dvejetainį kodą, negalėsite ją suderinti su kitais C ++ ABI (vardų apdorojimo, išimties tvarkymo) be recompiling iš šaltinio kodo.

ELF yra rinkmenos formatas, skirtas naudoti krautuvui ir dinaminiam saitui. ELF yra dvejetainio kodo ir duomenų talpyklos formatas, todėl nurodo kodo ABI dalį. Nenorėčiau, kad ELF būtų griežtai suprantama kaip ABI, nes PE vykdomosios yra ne ABI.

Visi ABI yra konkretūs nurodymų rinkiniai. ARM ABI neturės prasmės MSP430 ar x86_64 procesoriuje.

Windows sistemoje yra keletas ABI, pavyzdžiui, „fastcall“ ir „stdcall“ - tai du bendri ABI. ABI scenarijus vėl skiriasi.

8
23 марта '10 в 9:26 2010-03-23 09:26 Atsakymą pateikė Yann Ramin kovo 23 d. 10 val. 9:26 val. 2010-03-23 ​​09:26

Jums nereikia ABI, jei -

  • Jūsų programa neturi funkcijų, ir -
  • Jūsų programa yra vienas vykdomas failas, kuris veikia atskirai (tai yra įterptinė sistema), kur jis tiesiog veikia tik ir nereikia nieko pasakyti.

Supaprastinta santrauka:

API :. Čia rasite visas funkcijas, kurias galite skambinti.

ABI :. Taip galite skambinti funkcijai. "

ABI yra taisyklių rinkinys, kurį rengia kompiliatoriai ir sąsajos, kad sukompiliuotų programą, kad ji veiktų tinkamai. ABI apima kelias temas:

  • Galbūt didžiausia ir svarbiausia ABI dalis yra standartinis procedūros kvietimas , kurį kartais vadina „skambučių konvencija“. Priežastys, kodėl konvencijos standartizuoja „funkcijų“ vertimą į surinkimo kodą.
  • ABI taip pat apibrėžia, kaip turėtų būti rodomi viešųjų funkcijų pavadinimai bibliotekose, kad kitas kodas galėtų iškviesti šias bibliotekas ir žinoti, kurie argumentai turėtų būti perduoti. Tai vadinama „mangling“.
  • ABI taip pat nustato, kokių tipų duomenų tipai gali būti naudojami, kaip jie turėtų būti suderinti, ir kitos žemo lygio detalės.

Giliau pažvelgti į kvietimą teikti paraiškas, kurią, mano nuomone, sudaro ABI pagrindas:

Pati mašina neturi „funkcijos“ koncepcijos. Kai rašote funkciją aukšto lygio kalba, pvz., C, kompiliatorius sukuria surinkėjo kodo eilutę, pvz., _MyFunction1: Tai yra etiketė, kuri galiausiai bus išspręsta montuotojui. Ši etiketė rodo „funkcijos“ „pradžią“ surinkimo kode. Aukšto lygio kode, kai „skambinate“ šią funkciją, tai, ką jūs iš tikrųjų darote, sukelia CPU eiti į šios etiketės adresą ir toliau vykdo ten.

Rengiantis šuoliui, kompiliatorius turėtų atlikti daug svarbių dalykų. Skambinančioji konvencija atrodo kaip kontrolinis sąrašas, kurį kompiliatorius atlieka visa tai:

  • Pirma, kompiliatorius įterpia tam tikrą surinkimo kodą, kad išsaugotų dabartinį adresą, todėl, kai baigsite „funkciją“, procesorius gali grįžti į tinkamą vietą ir tęsti vykdymą.
  • Tada kompiliatorius generuoja surinkimo kodą, kad būtų perduoti argumentai.
    • Kai kurios sudėtingos konvencijos nurodo, kad argumentai turi būti stumiami ant kamino (žinoma tam tikra tvarka).
    • Kitose sutartyse teigiama, kad argumentai turi būti įtraukti į konkrečius registrus (priklausomai nuo jų duomenų tipų).
    • Kiti susitarimai nurodo, kad turite naudoti tam tikrą kamino ir registrų derinį.
  • Žinoma, jei šiuose registruose buvo kažkas svarbaus, šios vertybės dabar perrašomos ir prarandamos visam laikui, todėl kai kurios skambinančioji konvencija gali diktuoti, kad kompiliatorius turi išsaugoti kai kuriuos iš šių registrų prieš pateikdamas argumentus į juos.
  • Dabar kompiliatorius įterpia šuolio nurodymą, nurodydamas procesoriui eiti į ankstesnę etiketę ( _MyFunction1: . Šiuo metu jūs galite apsvarstyti procesoriaus „įtrauktą“ į savo „funkciją“.
  • Funkcijos pabaigoje kompiliatorius įdeda tam tikrą surinkimo kodą, dėl kurio CPU parašys grąžinimo vertę reikiamoje vietoje. Skambinančioji konvencija nustatys, ar grąžinimo reikšmė turi būti įrašyta į tam tikrą registrą (priklausomai nuo jo tipo) ar kamino.
  • Dabar atėjo laikas išvalyti. Skambinančioji konvencija nustatys, kur kompiliatorius pateikia valymo kūrimo kodą.
    • Kai kuriose konvencijose nustatyta, kad skambinantysis turi išvalyti kamino. Это означает, что после того, как "функция" будет выполнена, и процессор вернется туда, где он был раньше, самый следующий код, который должен быть выполнен, должен быть очень конкретным кодом очистки.
    • Другие соглашения говорят, что некоторые части кода очистки должны быть в конце "функции" перед скачком назад.