Kysymys:
Kysymys LEA-ohjeista
krystalgamer
2016-03-29 16:22:33 UTC
view on stackexchange narkive permalink

Oppin käänteisinsinööriä. Joten koodaan joitain ohjelmia ja yritän ymmärtää niiden kokoonpanoa. Törmäsin utelias tapaukseen, enkä usko, että en pysty ratkaisemaan sitä yksin.

Tässä on c-koodi:

  #include <stdio.h>int main () {char * texto = "O numero e% d \ n"; int i = 10; while (i) {printf (texto, i -);} return 0;} 

IDA: n tuottama kokoonpano on seuraava:

  mov eax, [esp + 28] lea edx, [eax-1]; Osa jota en ymmärrämov [esp + 28], edxmov [esp + 4], eaxmov eax, [esp + 18h] mov [esp], eax; char * call _printf  

Ymmärrän sen, että se tallentaa vanhan arvon eax: iin ja työntää pinoa (en tarkoituksella ole ottanut optimointia käyttöön) ja työntää sitten muodon. se tapahtuu keskellä, se tekee i-- , mutta en ymmärrä miten se toimii. Joten se saa osoitteen eax-1 ja tallentaa edx -kansioon ja tallentaa sen sitten i -kohtaan, mutta eax ei sisällä osoitetta vaan arvoa.

Kiitos etukäteen.

`lea edx, [blah-1]` on olennaisesti `mov edx, blah-1` (jälkimmäinen ei tietenkään ole kelvollinen komento)
Kaksi vastused:
Guntram Blohm supports Monica
2016-03-29 17:07:23 UTC
view on stackexchange narkive permalink

Näkemäsi on tehokkuustrikki, jota kääntäjät haluavat käyttää.

Sisäisesti CPU ei tee eroa numeroiden ja osoitteiden välillä - 32-bittiset kokonaisluvut ja osoittimet ovat sama asia. (Tai 64-bittinen, jos käytät uudempaa arkkitehtuuria, mutta kun rekisterinimesi alkavat e , käytät 32-bittistä).

lea käsky lataa operandin osoitteen itse operandin sijaan. C-termeillä voit tarkastella [eax-1] nimellä * (eax-1), ja lea lisää siihen & -operaattorin, joten lea edx , [eax-1] on kuin edx = & (* (eax-1)) . Mikä on tietysti sama kuin eax-1 .

Kääntäjä olisi voinut tehdä täsmälleen saman käyttämällä komentosarjaa mov edx, eax; sub edx, 1 tai mov edx, eax; vähennä edx . Joten miksi se käytti lea -käskyä?

Vastaus on, että historiallisesti osoitteiden ratkaiseminen lea -sovelluksessa tapahtui omistetulla osoiteväylälaitteistolla ja ohitti ALU: n. Myös putkistolla oli ongelmia, kun samaa rekisteriä käytettiin kahdesti seuraavissa toiminnoissa. Tämä tarkoittaa, että vanhemmissa prosessoreissa lea -toiminnon käyttäminen oli muutama sykli nopeampi kuin vaihtoehdot, eikä sitä ole vaikea toteuttaa kääntäjässä, joten kääntäjät tekivät näin perinteisesti.

Uusissa prosessoreissa erotusta " lea käyttää erillistä laitteistoa" ei tehdä (välttämättä) enää, ja putkisto on paljon älykkäämpi kuin aiemmin, joten epäilen, että sillä on merkitystä näinä päivinä. Mutta se on edelleen kääntäjissä, eikä sitä poisteta niistä, koska siihen ei ole mitään hyvää syytä.

& (* (Eax-1)): n ymmärtäminen helpottaa ongelmaa. Kiitos täydellisestä ja perusteellisesta vastauksesta!
Jopa tänään se pienentää koodin kokoa. Eikö se ole voitto?
@JanDvorak: Eikö EAX: n tallentaminen [ESP + 4]: een ja "dec eax" -toiminnon käyttäminen ja EAX: n [ESP + 28]: een tallentaminen lisää koodia? Tiedän, että nykyaikaiset suorittimet ovat hitaampia "inc": llä ja "dec": llä kuin "add", mutta luulen, että ne ovat edelleen yksitavuisia ohjeita, eikö olekin?
@Jan: Moderneilla kääntäjillä on taipumus aggressiivisesti pienimmässäkin provokaatiossa, joten vähäiset säästöt täällä ja siellä jäävät huomaamatta hyper-turvotuksen joukossa. Lisäksi suorittimilla on nykyään niin monta ALU: ta, että tuskin kukaan huomaa, että `lea` ei käytä mitään. `Lea` jättää liput yksin, se voi vähentää rekisteripainetta (aina ongelma x86-tilassa!) Ja se voi lyhentää riippuvuusketjuja. Mistä ei pidä? ;-)
Itse asiassa sillä on vielä paljon eroja. Tässä tapauksessa sukupolvi on typerää, koska vakio on 1, mutta useimmissa tapauksissa se on parempi kuin muuten käytettävä mov / add-pari tai jopa move / add / add tripletti.
ebux
2016-03-29 16:39:10 UTC
view on stackexchange narkive permalink

Intelin mukaan LEA-ohje on:

Tämä käsky laskee toisen operandin (lähde-operandi) todellisen osoitteen ja tallentaa sen ensimmäiseen operandiin (kohde-operandi). Lähdeoperandi on muistiosoite (offset-osa), joka on määritetty yhdellä prosessorin osoitetiloista; kohdeoperandi on yleiskäyttöinen rekisteri.

Joten, lea edx, [eax-1] laskee [eax-1] osoitteen ] , joka on eax-1, koska [] tarkoittaa, että operandia tulisi käsitellä osoitteena. Sen jälkeen osoite tallennetaan kohtaan edx .

Olen aina sekoittamassa ajattelurekistereitä, joilla on osoitteita .. Ymmärrän, että se vähentää 1. Kiitos!


Tämä Q & A käännettiin automaattisesti englanniksi.Alkuperäinen sisältö on saatavilla stackexchange-palvelussa, jota kiitämme cc by-sa 3.0-lisenssistä, jolla sitä jaetaan.
Loading...