Sumisid sa assembler. Isang kumpletong kurso sa programming sa Asma mula sa ][

Ang pagsusulat ng mga OS bootloader, mga driver, muling pagsusulat ng mga lugar ng memorya at iba pang mga gawain para sa pagtatrabaho sa isang computer ay ipinatupad gamit ang assembler. Ang mga piling aklat sa wika ng pagpupulong ay tutulong sa iyo na maunawaan ang prinsipyo ng pagpapatakbo ng isang wikang nakatuon sa makina at makabisado ito.

1. Revich Yu – Praktikal na programming ng Atmel AVR microcontrollers sa assembly language, 2014.

"Bagong dugo" sa larangan ng microcontroller programming. Ang mga tampok ng Atmel AVR ay inilarawan nang detalyado, mayroong isang listahan ng mga utos at handa na mga recipe - assembler na may mga halimbawa. Magandang bagay para sa mga radio amateur at inhinyero, bagama't ito ay angkop din para sa mga baguhan na coder: ang kasaysayan, mga pamilya at mga kakayahan ng AVR MK ay hinawakan. Kapansin-pansin na ang pagpapakilala ay laconic at mabilis na nakarating sa punto, kaya hindi na kailangang magreklamo tungkol sa mga liriko.

2. Kalashnikov O. – Ang wika ng pagpupulong ay simple. Pag-aaral sa programa, 2011

Isang tunay na treat para sa mga baguhan na nag-googling pa rin ng pangunahing terminolohiya at naghahanap ng isang aklat-aralin sa pagpupulong. Ito siya. Bilang karagdagan sa pamilyar sa iyong sarili sa wika at sa mga unang programa, ang mga punto ng sakit ay naaantig din - mga pagkagambala: isang simpleng bagay, ngunit sa una ay mahirap maunawaan. Sa bawat kabanata, ang mga aralin sa assembler ay nagiging mas kumplikado, at sa dulo ang mambabasa ay makakasulat ng mga programa sa assembler, i-optimize ang mga ito, gumana sa mga virus, antivirus, memorya at mga file system.

3. Ablyazov R. – Assembly language programming sa x86-64 platform, 2011

Ang diin ay sa pagpapatakbo ng processor sa protektadong mode at mahabang mode. Ito ay isang kailangang-kailangan na base para sa programming sa Win32 at Win64, na nakakaapekto sa mga utos ng assembler, interrupts, pagsasalin at mga mekanismo ng proteksyon, na isinasaalang-alang ang mga pagkakaiba sa mode. Isinasaalang-alang ang pag-unlad mga windowed application at mga driver. Ang assembler na ito Ang aklat-aralin ay angkop para sa mga baguhan na coder at sa mga agad na lumipat sa assembly language programming, ngunit may kaunting pag-unawa sa x86-64 hardware platform.

4. Stolyarov A. – Programming sa NASM assembly language para sa Unix OS, 2011.

Mula sa terminolohiya hanggang sa pakikipag-ugnayan sa OS, ito ay, nang walang pagmamalabis, isa sa mga pinakamahusay pantulong sa pagtuturo. Para sa mga gustong matuto ng assembly language programming ngunit ayaw mag-overload ng kanilang bookshelf, sapat na ang textbook na ito. Ang syntax ng NASM assembly language ay inilarawan nang detalyado, mga rehistro at memorya, mga pagpapatakbo ng iba't ibang kumplikado, mga utos ay hinawakan, at mga halimbawa ay ibinigay din.

Upang maisagawa ng makina ang mga utos ng tao antas ng hardware, ito ay kinakailangan upang magtakda ng isang tiyak na pagkakasunud-sunod ng mga aksyon sa wika ng "zero at isa". Ang nagtitipon ay magiging isang katulong sa bagay na ito. Ito ay isang utility na gumagana sa pagsasalin ng mga command sa machine language. Gayunpaman, ang pagsulat ng isang programa ay isang napakahirap at kumplikadong proseso. Ang wikang ito ay hindi inilaan upang lumikha ng mga baga at mga simpleng aksyon. Naka-on sa ngayon anumang programming language na ginagamit (Assembler works great) ay nagbibigay-daan sa iyo na magsulat ng espesyal mabisang gawain, na lubos na nakakaapekto sa pagganap ng hardware. Ang pangunahing layunin ay lumikha ng mga micro-instructions at maliliit na code. Nagbibigay ang wikang ito mas maraming posibilidad kaysa, halimbawa, Pascal o C.

Isang Maikling Paglalarawan ng Mga Wika ng Assembly

Ang lahat ng mga programming language ay nahahati sa mga antas: mababa at mataas. Ang alinman sa mga syntactic system ng "pamilya" ng Assembler ay nakikilala sa pamamagitan ng katotohanan na agad nitong pinagsasama ang ilan sa mga pakinabang ng pinakakaraniwan at modernong mga wika. Ang pagkakapareho nila sa iba ay ang ganap nilang magagamit ang computer system.

Ang isang natatanging tampok ng compiler ay ang kadalian ng paggamit nito. Ito ay nakikilala ito mula sa mga gumagana lamang na may mataas na antas. Kung isasaalang-alang mo ang anumang naturang programming language, gumagana ang Assembler nang dalawang beses nang mas mabilis at mas mahusay. Upang magsulat dito madaling programa, hindi ito magtatagal ng masyadong maraming oras.

Maikling tungkol sa istruktura ng wika

Kung pinag-uusapan natin sa pangkalahatan ang tungkol sa gawain at istraktura ng wika, masasabi nating sigurado na ang mga utos nito ay ganap na tumutugma sa mga utos ng processor. Iyon ay, ang assembler ay gumagamit ng mga mnemonic code, karamihan komportable para sa isang tao para sa pagre-record.

Hindi tulad ng ibang mga programming language, ang Assembly ay gumagamit ng mga partikular na label sa halip na mga address para magsulat ng mga memory cell. Kasama ang proseso ng pagpapatupad ng code, isinalin ang mga ito sa tinatawag na mga direktiba. Ito mga kamag-anak na address, na hindi nakakaapekto sa pagpapatakbo ng processor (ay hindi isinalin sa machine language), ngunit kinakailangan para sa pagkilala ng programming environment mismo.

Ang bawat linya ng processor ay may sariling Sa sitwasyong ito, ang anumang proseso, kabilang ang isinalin, ay magiging tama

Ang wika ng assembly ay may ilang mga syntax na tatalakayin sa artikulo.

Mga kalamangan ng wika

Ang pinakamahalaga at maginhawang aparato ng wika ng Assembly ay maaari kang magsulat ng anumang programa para sa processor sa loob nito, na magiging napaka-compact. Kung ang code ay naging malaki, pagkatapos ay ang ilang mga proseso ay na-redirect sa RAM. Bukod dito, ginagawa nila ang lahat nang mabilis at walang mga pagkabigo, maliban kung, siyempre, pinamamahalaan sila ng isang kwalipikadong programmer.

Ang mga driver, operating system, BIOS, compiler, interpreter, atbp. ay lahat ng mga programa sa Assembly language.

Kapag gumagamit ng disassembler na nagsasagawa ng pagsasalin mula sa makina patungo sa makina, madali mong maunawaan kung paano gumagana ito o ang gawain ng system na iyon, kahit na walang paliwanag para dito. Gayunpaman, ito ay posible lamang kung ang mga programa ay madali. Sa kasamaang palad, ang mga non-trivial code ay medyo mahirap maunawaan.

Mga disadvantages ng wika

Sa kasamaang palad, ang mga baguhang programmer (at madalas na mga propesyonal) ay nahihirapang maunawaan ang wika. Ang assembler ay nangangailangan detalyadong paglalarawan kinakailangang utos. Dahil sa pangangailangang gumamit ng mga utos ng makina, tumataas ang posibilidad ng mga maling aksyon at ang pagiging kumplikado ng pagpapatupad.

Upang magsulat kahit na ang pinaka isang simpleng programa, ang programmer ay dapat na kwalipikado, at ang kanyang antas ng kaalaman ay sapat na mataas. Ang karaniwang espesyalista, sa kasamaang-palad, ay madalas na nagsusulat ng masamang code.

Kung ang platform kung saan nilikha ang programa ay na-update, kung gayon ang lahat ng mga utos ay dapat na muling isulat nang manu-mano - ito ay kinakailangan ng wika mismo. Hindi sinusuportahan ng assembler ang function awtomatikong regulasyon operability ng mga proseso at pagpapalit ng anumang elemento.

Mga utos ng wika

Tulad ng nabanggit sa itaas, ang bawat processor ay may sariling hanay ng mga utos. Ang pinakasimpleng elemento na kinikilala ng anumang uri ay ang mga sumusunod na code:


Paggamit ng Mga Direktiba

Pagprograma ng mga microcontroller sa wika (pinapayagan ito ng Assembler at mahusay na nakayanan ang paggana) mismo mababang antas sa karamihan ng mga kaso ito ay matagumpay na nagtatapos. Pinakamainam na gumamit ng mga processor na may limitadong mapagkukunan. Para sa 32-bit na teknolohiya binigay na wika akma nang perpekto. Madalas mong makikita ang mga direktiba sa code. Ano ito? At para saan ito ginagamit?

Una, kinakailangang bigyang-diin na ang mga direktiba ay hindi isinasalin sa wika ng makina. Kinokontrol nila kung paano ginagawa ng compiler ang trabaho. Hindi tulad ng mga utos, ang mga parameter na ito, pagkakaroon iba't ibang function, naiiba hindi salamat sa iba't ibang mga processor, ngunit sa kapinsalaan ng isa pang tagasalin. Kabilang sa mga pangunahing direktiba ay ang mga sumusunod:


Pinagmulan ng pangalan

Paano nakuha ng wika ang pangalan nito - "Assembler"? Pinag-uusapan natin ang tungkol sa isang tagasalin at isang compiler, na nag-encrypt ng data. Sa English, ang Assembler ay nangangahulugang walang iba kundi isang assembler. Ang programa ay hindi binuo nang manu-mano ang isang awtomatikong istraktura ay ginamit. Bukod dito, sa ngayon, nawala na sa mga user at espesyalista ang pagkakaiba sa pagitan ng mga termino. Ang mga programming language ay madalas na tinatawag na assembler, bagaman ito ay isang utility lamang.

Dahil sa karaniwang kolektibong pangalan, ang ilang mga tao ay nagkakamali na naniniwala na mayroong isang mababang antas ng wika (o mga karaniwang pamantayan para dito). Upang maunawaan ng programmer kung anong istraktura ang pinag-uusapan natin, kinakailangan na linawin kung aling platform ang ginagamit ng isang partikular na wika ng Assembly.

Macro ibig sabihin

Ang mga wika ng assembly, na medyo bago, ay may mga macro feature. Ginagawa nilang mas madali ang parehong magsulat at magpatakbo ng isang programa. Salamat sa kanilang presensya, ang tagasalin ay nagpapatupad ng nakasulat na code nang maraming beses nang mas mabilis. Kapag gumagawa ng conditional na pagpili, maaari kang magsulat ng malaking bloke ng mga command, ngunit mas madaling gumamit ng mga macro tool. Papayagan ka nitong mabilis na magpalipat-lipat sa pagitan ng mga aksyon kung ang isang kundisyon ay natutugunan o hindi.

Kapag gumagamit ng mga macro language directive, ang programmer ay tumatanggap ng Assembler macros. Minsan maaari itong malawak na gamitin, at kung minsan ito functional na mga tampok nabawasan sa isang koponan. Ang kanilang presensya sa code ay ginagawang mas madaling gamitin, ginagawa itong mas naiintindihan at nakikita. Gayunpaman, dapat ka pa ring mag-ingat - sa ilang mga kaso, ang mga macro, sa kabaligtaran, ay nagpapalala sa sitwasyon.

Pagkatapos ng maraming taon ng paggawa ng lahat nang walang tagumpay, nagpasya akong bumalik sa pinagmulan. Sa programming. Muli, dahil sa maraming "modernong tagumpay" sa lugar na ito, mahirap magpasya kung ano ang talagang kulang, kung ano ang dapat gawin upang ito ay maging kaaya-aya at kapaki-pakinabang. Ang pagkakaroon ng pagsubok ng maraming bagay nang unti-unti, nagpasya pa rin akong bumalik sa kung saan ako iginuhit mula sa mga unang araw ng aking pagkakakilala sa isang computer (kahit na may isang kopya ng paglikha ni Sir Sinclair) - sa programming sa wika ng pagpupulong. Sa katunayan, minsan kilala ko ang assembler (sa sa kasong ito Pinag-uusapan ko ang tungkol sa x86), ngunit wala akong isinulat dito sa loob ng halos 15 taon. Kaya, ito ay isang uri ng pagbabalik ng “prodigal son.”
Ngunit dito naghihintay ang unang pagkabigo. Ang mga libro, manwal at iba pang mga sangguniang libro sa assembler na matatagpuan sa Internet, sa aking labis na panghihinayang, ay naglalaman ng isang minimum na impormasyon tungkol sa kung paano mag-program sa assembler, kung bakit ito ay ganito, at kung ano ang ibinibigay nito.

Halimbawa mula sa ibang lugar

Kung kukunin natin ang boksing bilang isang halimbawa, kung gayon ang lahat ng naturang mga manwal ay nagtuturo kung paano magsagawa ng welga, gumalaw habang nakatayo sa sahig, ngunit kung ano ang ginagawang boksing - boksing, at hindi "pinahihintulutang pagsuntok" - ay ganap na nawawala. Iyon ay, kumbinasyon ng trabaho, mga tampok ng paggamit ng singsing, mga aksyong nagtatanggol, taktikal na istraktura ng labanan at, lalo na, ang diskarte sa labanan ay hindi isinasaalang-alang. Tinuruan nila ang isang tao na tamaan ang punching bag at dumiretso sa ring. Ito ay sa panimula ay mali. Ngunit ito ay eksakto kung paano nakaayos ang halos lahat ng "mga aklat-aralin" at "gabay" sa programming language ng assembly.


Gayunpaman, dapat may mga normal na libro; Samakatuwid, bago palitan ang kaalaman sa isang pandaigdigang paglalarawan ng arkitektura, mnemonics at lahat ng uri ng mga trick "kung paano gumawa ng isang fig sa 2 daliri," lapitan natin ang isyu ng programming language ng assembly mula sa isang "ideological" na pananaw.

Idyll?

Isang maliit na tala, higit pa sa teksto ay gagamit ng isang klasipikasyon na naiiba sa kasalukuyang karaniwang isa. Gayunpaman, hindi ito isang dahilan para sa "mga pagtatalo tungkol sa kulay ng katotohanan" lamang na sa form na ito ay mas madaling ipaliwanag ang pananaw ng may-akda sa programming.

Kaya, ngayon, tila, isang panahon ng kaligayahan ang dumating para sa mga programmer. Malaking seleksyon pondo para sa lahat ng okasyon at kagustuhan. Dito mayroon kang milyun-milyong "frameworks"/"patterns"/"templates"/"library" at libu-libong tool na "gumagawa ng programming", daan-daang wika at diyalekto, dose-dosenang metodolohiya at iba't ibang diskarte sa programming. Kunin mo - ayoko. Ngunit hindi ito "kumuha." At ang punto ay hindi sa mga paniniwala sa relihiyon, ngunit sa katotohanan na ang lahat ay mukhang isang pagtatangka na kumain ng isang bagay na walang lasa. Kung gusto mo at masigasig, maaari mong ibagay ito, siyempre. Ngunit, pagbalik sa programming, sa karamihan ng inaalok ay walang teknikal na kagandahan - maraming "saklay" lamang ang nakikita. Bilang resulta, kapag ginagamit ang mga "achievement" na ito, mula sa ilalim ng "brush ng mga artista", sa halip na nakakaakit ng mga landscape, isang solidong "abstraction" ang lalabas, o mga sikat na print - kung ikaw ay mapalad. Ang karamihan ba sa mga programmer ay talagang napakakaraniwan, ignorante at may mga problema sa antas ng genetic? Hindi, sa tingin ko ay hindi. Kaya ano ang dahilan?
Ngayon maraming mga ideya at paraan ng programming. Tingnan natin ang pinaka-“fashionable” sa kanila.

  • Imperative programming - sa diskarteng ito, tinutukoy ng programmer ang isang pagkakasunod-sunod ng mga aksyon na humahantong sa paglutas ng isang problema. Ito ay batay sa paghahati ng programa sa mga bahagi na nagsasagawa ng lohikal na independiyenteng mga operasyon (mga module, function, procedure). Ngunit hindi tulad ng na-type na diskarte (tingnan sa ibaba), mayroon mahalagang katangian- kakulangan ng "pag-type" ng mga variable. Sa madaling salita, walang konsepto ng "uri ng variable" sa halip, ang pag-unawa ay ginagamit na ang mga halaga ng parehong variable ay maaaring magkaroon ng iba't ibang uri. Mga kilalang kinatawan diskarteng ito ay Basic, REXX, MUMPS.
  • Naka-type na programming - pagbabago imperative programming kapag nililimitahan ng programmer at ng system ang mga posibleng halaga ng mga variable. Ang pinakasikat na mga wika ay Pascal, C.
  • Ang functional programming ay higit pa pamamaraan ng matematika paglutas ng isang problema, kapag ang solusyon ay binubuo sa "pagbuo" ng isang hierarchy ng mga function (at, nang naaayon, paglikha ng mga nawawala), na humahantong sa solusyon ng problema. Bilang mga halimbawa: Lisp, Forth.
  • Ang awtomatikong programming ay isang diskarte kung saan ang programmer ay bumubuo ng isang modelo/network na binubuo ng mga object/executive na elemento na nagpapalitan ng mga mensahe, parehong nagbabago/nag-iimbak ng kanilang panloob na "estado" at nagagawang makipag-ugnayan sa labas ng mundo. Sa madaling salita, ito ang karaniwang tinatawag na " object programming"(hindi object-oriented). Ang ganitong paraan ng programming ay ipinakilala sa Smalltalk.
Ngunit ano ang tungkol sa maraming iba pang mga wika? Bilang isang patakaran, ang mga ito ay "mutants" na. Halimbawa, ang paghahalo ng mga diskarteng nakabatay sa uri at automata ay nagbunga ng "object-oriented programming."

Tulad ng nakikita natin, ang bawat isa sa mga diskarte (kahit na hindi isinasaalang-alang ang mga limitasyon ng mga tiyak na pagpapatupad) ay nagpapataw ng sarili nitong mga paghihigpit sa pamamaraan ng programming mismo. Ngunit hindi ito maaaring iba. Sa kasamaang palad, ang mga paghihigpit na ito ay kadalasang ginawang artipisyal upang "mapanatili ang kadalisayan ng ideya." Bilang resulta, ang programmer ay kailangang "ibahin" ang unang nahanap na solusyon sa isang anyo na kahit papaano ay tumutugma sa ideolohiya ng wikang ginamit o ang "pattern" na ginamit. Ito ay kahit na hindi isinasaalang-alang ang mga bagong pamamaraan at pamamaraan ng disenyo at pag-unlad.

Tila kapag nagprograma sa assembler, malaya tayong gawin ang anuman at gayunpaman ang gusto natin at pinapayagan tayo ng hardware. Ngunit sa sandaling nais naming gamitin " unibersal na driver"Para sa anumang uri ng kagamitan, napipilitan kaming ipagpalit ang kalayaan ng "pagkamalikhain" para sa mga inireseta (standardized) na mga diskarte at paraan ng paggamit ng driver. Sa sandaling kailangan namin ng pagkakataon na gamitin ang gawain ng iba pang mga kasamahan o bigyan sila ng pagkakataon na gawin din ang mga bunga ng aming paggawa, napipilitan kaming baguhin ang kalayaan sa pagpili ng pakikipag-ugnayan sa pagitan ng mga bahagi ng programa sa ilang napagkasunduan. / mga pamantayang pamamaraan.

Kaya, ang "kalayaan" na iyon kung saan madalas na sinisikap ng mga tao na makapasok sa assembler ay madalas na nagiging isang "mito". At ito (pag-unawa sa mga limitasyon at mga paraan ng pag-aayos ng mga ito), sa aking palagay, ay dapat bigyan ng higit na pansin. Dapat na maunawaan ng programmer ang dahilan ng mga paghihigpit na ipinakilala, at kung ano ang pagkakaiba ng wika ng pagpupulong mula sa maraming wika mataas na antas, magagawang baguhin ang mga ito kung may ganoong pangangailangan. Gayunpaman, ngayon ang isang programmer ng wika ng pagpupulong ay napipilitang magtiis sa mga paghihigpit na ipinakilala ng mga mataas na antas ng mga wika, nang walang mga "karot" na magagamit sa mga programming sa kanila. Sa isang banda, ang mga operating system ay nagbibigay ng maraming naipatupad na mga pag-andar, may mga yari na aklatan at marami pang iba. Ngunit ang mga paraan ng paggamit ng mga ito, bilang isang espesyal na layunin, ay ipinatupad nang hindi isinasaalang-alang ang pagtawag sa kanila mula sa mga programang nakasulat sa wika ng pagpupulong, at kahit na sa pangkalahatan ay salungat sa lohika ng programming para sa x86 architecture. Bilang resulta, ngayon ang programming sa assembly language na may pagtawag sa mga function ng OS o panlabas na high-level na mga library ng wika ay "takot" at "katakutan".

Ang mas malayo sa kagubatan, mas makapal

Kaya, napagtanto namin na kahit na ang assembler ay napaka-simple, kailangan mong malaman kung paano ito gamitin. At ang pangunahing pagkakaugnay ay ang pangangailangan na makipag-ugnayan sa kapaligiran ng pagpapatupad kung saan tumatakbo ang aming programa. Kung ang mga programmer sa mataas na antas ng mga wika ay mayroon nang access sa mga kinakailangang aklatan, function, subroutine para sa maraming okasyon at mayroon silang access sa mga paraan ng pakikipag-ugnayan sa labas ng mundo, sa isang anyo na naaayon sa ideya ng wika, kung gayon ang isang assembler programmer ay kailangang tumawid sa isang kasukalan ng lahat ng uri ng mga hadlang na itinayo mula sa scratch. Kung titingnan mo kung ano ang nabubuo ng mga high-level na wika kapag pinagsama-sama, mararamdaman mo na ang mga sumulat ng mga compiler ay maaaring walang ideya kung paano gumagana ang isang processor na may x86 architecture, "o isa sa dalawa" (c).

Kaya, gawin natin ito sa pagkakasunud-sunod. Ang programming ay, una sa lahat, engineering, iyon ay, siyentipikong pagkamalikhain na naglalayong isang epektibong (sa mga tuntunin ng pagiging maaasahan, paggamit ng mga magagamit na mapagkukunan, oras ng pagpapatupad at kadalian ng paggamit) na solusyon praktikal na mga problema. At, ang batayan ng anumang engineering ay isang diskarte sa sistema. Iyon ay, ang anumang solusyon ay hindi maaaring ituring bilang isang uri ng "indivisible" black box na gumagana sa isang kumpleto at perpektong vacuum.

Isa pang halimbawa mula sa ibang lugar

Bilang isang maliwanag na halimbawa sistematikong diskarte Maaari mong banggitin ang produksyon ng mga trak sa USA. Sa kasong ito, ang tagagawa ng trak ay ang tagagawa lamang ng frame at taksi + ang taga-disenyo ng assembler. Lahat ng iba pa (engine, transmission, suspension, electrical equipment, atbp.) ay kinukuha batay sa kagustuhan ng customer. Gusto ng isang customer na makakuha ng isang Kenworth na may makina mula sa Detroit Diesel, isang Fuller manual transmission, leaf spring suspension mula sa ilang Dana - mangyaring. Ang isang kaibigan ng customer na ito ay nangangailangan ng parehong modelo ng Kenworth, ngunit may isang "katutubong" Paccar engine, isang Allison automatic transmission at air suspension mula sa ibang manufacturer - madali! At gayon din ang lahat ng mga nagtitipon ng trak sa USA. Ibig sabihin, ang isang trak ay isang sistema kung saan ang bawat module ay maaaring palitan ng isa pa para sa parehong layunin at walang putol na naka-dock sa mga umiiral na. Bukod dito, ang paraan ng mga docking module ay ginawa gamit ang maximum na magagamit na versatility at kaginhawahan karagdagang pagpapalawak functionality. Ito ang dapat pagsikapan ng isang inhinyero.

Sa kasamaang palad, kailangan nating mamuhay sa kung ano ang mayroon tayo, ngunit sa hinaharap dapat itong iwasan. Kaya, ang isang programa ay, sa esensya, isang set ng mga module (hindi mahalaga kung ano ang tawag sa kanila o kung paano sila "kumikilos"), sa pamamagitan ng pagbubuo kung saan nakakamit natin ang isang solusyon sa problemang nasa kamay. Para sa kahusayan, lubos na kanais-nais na ang mga modyul na ito ay maaaring magamit muli. At hindi lamang gamitin sa anumang halaga, ngunit gamitin sa isang maginhawang paraan. At narito ang isa pang hindi kasiya-siyang "sorpresa" na naghihintay sa amin. Karamihan sa mga wikang may mataas na antas ay gumagana sa mga yunit ng istruktura tulad ng "function" at "procedure". At, bilang isang paraan upang makipag-ugnayan sa kanila, ginagamit ang "mga passing parameter". Ito ay lubos na lohikal, at walang mga tanong na lumabas dito. Ngunit gaya ng dati, "hindi kung ano ang ginawa ang mahalaga, kung paano ito ginagawa" (c). At dito nagsisimula ang pinaka hindi maintindihan na bahagi. Ngayon, mayroong 3 karaniwang paraan upang ayusin ang paglipat ng mga parameter: cdecl, stdcall, fastcall. Kaya, wala sa mga pamamaraang ito ang "katutubo" para sa x86. Bukod dito, lahat ng mga ito ay may depekto mula sa punto ng view ng pagpapalawak ng pag-andar ng tinatawag na mga subroutine. Ibig sabihin, sa pamamagitan ng pagtaas ng bilang ng mga parameter na naipasa, napipilitan kaming baguhin ang lahat ng call point ng function/subroutine na ito, o lumikha ng bagong subroutine na may katulad na functionality, na tatawagin sa bahagyang naiibang paraan.

Ang mga pamamaraan sa itaas ng pagpasa ng mga parameter ay medyo mahusay na gumagana sa mga processor na may 2 magkahiwalay na stack (isang stack ng data at isang address/control stack) at nakabuo ng mga stack manipulation command (hindi bababa sa pag-index ng access sa mga elemento ng stack). Ngunit kapag nagprograma sa x86, kailangan mo munang i-distort kapag nagpapasa/ tumatanggap ng mga parameter, at pagkatapos ay tandaan na "istraktura" na alisin ang mga ito mula sa stack. Kasabay nito, sinusubukang hulaan/kalkulahin ang maximum na lalim ng stack. Alalahanin natin na ang x86 (16/32 bit mode) ay isang processor na may:

  • mga dalubhasang rehistro (mga RON - mga rehistro ng pangkalahatang layunin - ay wala nang ganito: ibig sabihin, hindi natin, sa isang utos, i-multiply ang mga nilalaman ng rehistro ng GS sa halaga mula sa EDI at makuha ang resulta sa pares ng EDX:ECX, o hatiin ang halaga mula sa EDI:ESI register pair sa pamamagitan ng content register EAX);
  • mayroong ilang mga rehistro;
  • isang stack;
  • ang lokasyon ng memorya ay hindi nagbibigay ng anumang impormasyon tungkol sa uri ng halaga na nakaimbak doon.
Sa madaling salita, ang mga diskarte sa programming na ginagamit para sa mga processor na may malaking file ng rehistro, suporta para sa maramihang mga independiyenteng stack, atbp. Karamihan ay hindi naaangkop kapag nagprograma sa x86.

Ang susunod na tampok ng pakikipag-ugnayan sa mga nakahandang module na nakasulat sa "mga wikang may mataas na antas" ay ang "pakikibaka" na may "mga uri ng variable". Sa isang banda, ang dahilan para sa paglitaw ng mga uri ng variable ay malinaw - alam ng programmer kung anong mga halaga ang ginagamit sa loob ng kanyang subroutine / module. Batay dito, tila lohikal na sa pamamagitan ng pagtatakda ng uri ng mga halaga ng isang variable, maaari nating "pasimplehin" ang pagsulat ng isang programa sa pamamagitan ng pagtitiwala sa kontrol ng mga uri/mga limitasyon ng halaga sa tagasalin ng wika. Ngunit kahit dito ay itinapon ang sanggol kasama ng tubig sa paliguan. Dahil ang anumang programa ay isinulat hindi upang makabuo ng mga spherical na kabayo sa isang vacuum, ngunit upang praktikal na gawain gamit ang data ng gumagamit. Iyon ay, isang malinaw na paglabag sa diskarte sa mga system - na parang ang mga developer ng mga high-level na wika ay isinasaalang-alang ang kanilang mga system nang hindi isinasaalang-alang ang pakikipag-ugnayan sa labas ng mundo. Bilang resulta, kapag nagprograma sa isang nai-type na wika, dapat na asahan ng developer ang lahat ng posibleng uri ng "maling" input na data, at maghanap ng mga paraan upang malutas ang mga kawalan ng katiyakan. At dito pumapasok ang napakalaking support system. mga regular na expression, pagpoproseso mga pambihirang sitwasyon, mga lagda/pamamaraan para sa iba't ibang uri mga halaga at iba pang henerasyon ng mga saklay.

Tulad ng nabanggit sa itaas, para sa arkitektura ng x86, ang halaga mismo na nakaimbak sa isang memory cell ay walang anumang uri. Ang assembler programmer ay tumatanggap ng pribilehiyo at responsibilidad para sa pagtukoy kung paano iproseso ang mismong halagang ito. Tulad ng para sa kung paano matukoy ang uri ng isang halaga at kung paano iproseso ito, maraming mga pagpipilian na mapagpipilian. Ngunit, bigyang-diin nating muli, lahat ng mga ito ay nauugnay lamang sa mga halaga na natanggap mula sa gumagamit. Tulad ng wastong nabanggit ng mga developer ng mga nai-type na wika: ang mga uri ng mga halaga ng panloob at mga variable ng serbisyo ay halos palaging kilala nang maaga.

Ang kadahilanang ito (baluktot na pagpasa ng mga parameter sa mga module na nakasulat sa mataas na antas ng mga wika at ang pangangailangan na mahigpit na subaybayan ang mga uri ng mga parameter na ipinapasa sa parehong mga module) ay tila ang pangunahing dahilan kung bakit ang programming sa assembly language ay hindi makatwirang mahirap. At mas pinipili ng nakararami na unawain ang kagubatan ng “mga wikang may mataas na antas” upang samantalahin ang mga nagawa na ng iba, kaysa magdusa, ipasok ang parehong “standard” na saklay upang itama ang hindi nila ginawa. At ito ay isang bihirang tagasalin ng assembler na kahit papaano ay "nagpapaginhawa" sa programmer mula sa gawaing ito.

Ano ang gagawin?

Mga paunang konklusyon na isinasaalang-alang ang 15 taon break sa assembly language programming.
Una, tungkol sa mga module o bahagi ng programa. Sa pangkalahatan, sulit na makilala ang dalawang uri ng mga executive module ng isang programa sa wika ng pagpupulong - "operasyon" at "subroutine".
  • Ang isang "operasyon" ay isang module na nagsasagawa ng isang "atomic" na aksyon at hindi nangangailangan ng maraming mga parameter para sa pagpapatupad nito (halimbawa, ang operasyon ng pag-clear sa buong screen, o ang operasyon ng pagkalkula ng median serye ng numero atbp.).
  • Ang isang "subroutine" ay dapat na tinatawag na isang functional module na nangangailangan, para sa tamang paggana, ng maraming input parameter (higit sa 2x-3x).
At dito ito ay nagkakahalaga ng pagtatasa ng karanasan ng imperative at mga functional na wika. Binigyan nila kami ng 2 mahalagang tool na sulit na gamitin: "struktura ng data" (o, gamit ang REXX bilang halimbawa, compound/augmentable variable) at "data non-mutability".

Kapaki-pakinabang din na sundin ang panuntunan ng non-mutability - iyon ay, ang immutability ng mga naipasa na parameter. Ang subroutine ay hindi maaaring (hindi dapat) baguhin ang mga halaga sa istraktura na ipinasa dito at ang resulta ay ibinalik alinman sa mga rehistro (hindi hihigit sa 2-3 mga parameter), o din sa isang bagong istraktura na nilikha. Kaya, tayo ay napalaya mula sa pangangailangang gumawa ng mga kopya ng mga istruktura kung sakaling may "nakalimutan" na mga pagbabago sa data ng mga subroutine, at maaari nating gamitin ang nabuo nang istraktura nang buo o ang pangunahing bahagi nito upang tumawag sa ilang mga subroutine na tumatakbo na may pareho/katulad na hanay ng mga parameter . Bukod dito, halos awtomatiko tayong nakarating sa susunod na "functional" na panuntunan - ang panloob na konteksto-pagsasarili ng mga subroutine at operasyon. Sa madaling salita, sa paghihiwalay ng estado/data mula sa pamamaraan/subroutine ng kanilang pagproseso (kumpara sa awtomatikong modelo). Sa mga kaso parallel programming, at gayundin pagbabahagi Gamit ang isang subroutine, inaalis namin pareho ang pangangailangang lumikha ng maraming konteksto ng pagpapatupad at subaybayan ang kanilang "hindi intersection", at mula sa paggawa ng maraming pagkakataon ng isang subroutine na may iba't ibang "estado" sa kaso ng ilang mga tawag.

Tulad ng para sa "mga uri" ng data, dito maaari mong iwanan ang "lahat ng bagay", o maaari mo ring hindi muling likhain ang gulong at gamitin kung ano ang matagal nang ginagamit ng mga developer ng imperative language translator - ang "value type identifier". Ibig sabihin, lahat ng data na nagmumula labas ng mundo ay sinusuri at ang bawat resultang value ay bibigyan ng identifier ng uri na pinoproseso (integer, float, naka-pack na BCD, character code, atbp.) at ang laki ng field/value. Ang pagkakaroon ng impormasyong ito, ang programmer, sa isang banda, ay hindi pinipilit ang gumagamit sa isang hindi kinakailangang makitid na balangkas ng "mga panuntunan" para sa pagpasok ng mga halaga, at sa kabilang banda, ay may pagkakataon na pumili ng pinaka-epektibong paraan upang maproseso ang data ng gumagamit sa panahon ng proseso ng trabaho. Ngunit, inuulit ko muli, nalalapat lamang ito sa pagtatrabaho sa data ng user.

Ang mga ito ay pangkalahatang pagsasaalang-alang tungkol sa programming language ng assembly, hindi nauugnay sa mga isyu sa disenyo, pag-debug at paghawak ng error. Umaasa ako na ang mga developer ng OS na sumulat sa kanila mula sa simula (at higit pa sa assembler) ay magkakaroon ng isang bagay na pag-isipan at pipiliin nila (kahit na hindi ang mga inilarawan sa itaas, ngunit anumang iba pa) mga paraan upang gawing mas sistematiko, maginhawa ang programming sa assembler at kasiya-siya, at Hindi nila basta-basta kokopyahin ang ibang tao, kadalasang walang pag-asa na "baluktot" na mga opsyon.

Ngayon ay mayroong isang malaking bilang ng mga high-level na programming language. Laban sa kanilang background, programming in mababang antas ng wika- assembler - maaaring sa unang tingin ay parang isang bagay na hindi napapanahon at hindi makatwiran. Gayunpaman, ito ay tila lamang. Dapat itong kilalanin na ang assembler ay talagang isang wika ng processor, na nangangahulugang hindi ito magagawa nang wala ito hangga't umiiral ang mga processor. Ang pangunahing bentahe ng assembly language programming ay pinakamataas na pagganap at ang pinakamababang laki ng natanggap na mga programa.

Ang mga disadvantages ay kadalasang dahil lamang sa hilig modernong pamilihan mas gusto ang dami kaysa kalidad. Mga modernong kompyuter ay madaling makayanan ang isang bungkos ng mga command ng mataas na antas ng mga function, at kung hindi ito madali, mangyaring i-update ang hardware ng iyong makina! Ito ang batas ng komersyal na programming. Kung pinag-uusapan natin tungkol sa programming para sa kaluluwa, kung gayon ang isang compact at maliksi na programa na nakasulat sa wikang pagpupulong ay mag-iiwan ng mas kaaya-ayang impresyon kaysa sa isang mataas na antas na hulk na nabibigatan ng isang grupo ng mga hindi kinakailangang operasyon. May opinyon na piling iilan lamang ang maaaring magprogram sa assembler. Hindi ito totoo. Siyempre, ang mga mahuhusay na assembler programmer ay mabibilang sa isang banda, ngunit ito ang kaso sa halos anumang lugar ng aktibidad ng tao. Walang gaanong mga ace driver, ngunit kahit sino ay maaaring matutong magmaneho ng kotse kung sila ay may pagnanais. Matapos basahin ang seryeng ito ng mga artikulo, hindi ka magiging isang cool na hacker. Gayunpaman matatanggap mo pangkalahatang impormasyon at matuto mga simpleng paraan assembly language programming para sa Windows, gamit ang mga built-in na function nito at mga tagubilin sa macro ng compiler. Naturally, upang makabisado ang Windows programming, kailangan mong magkaroon ng mga kasanayan at karanasan sa Windows. Sa una ay hindi ka gaanong mauunawaan, ngunit huwag kang mabalisa dito at magbasa: sa paglipas ng panahon, ang lahat ay mahuhulog sa lugar.

Kaya, upang simulan ang programming, kailangan namin ng isang compiler. Ang compiler ay isang program na nagsasalin ng source code na isinulat ng isang programmer sa isang bagay na maipapatupad ng processor. code ng makina. Karamihan sa mga assembler textbook ay nakatuon sa paggamit ng MASM32 (Microsoft Macro Assembler) package. Ngunit bilang isang uri ng pagkakaiba-iba at para sa maraming iba pang mga kadahilanan, ipapakilala ko sa iyo ang batang compiler na FASM (Flat Assembler), na mabilis na nakakakuha ng katanyagan. Ang compiler na ito ay medyo madaling i-install at gamitin, compact at mabilis, ay may mayaman at malawak na macro syntax na nagbibigay-daan sa iyo upang i-automate ang marami mga nakagawiang gawain. Ang kanyang pinakabagong bersyon maaari mong i-download sa: website sa pamamagitan ng pagpili ng flat assembler para sa Windows. Upang i-install ang FASM, lumikha ng isang folder, halimbawa, "D:\FASM" at i-extract ang mga nilalaman ng na-download na zip archive dito. Patakbuhin ang FASMW.EXE at isara nang walang pagbabago. By the way, kung gagamitin mo karaniwang konduktor, at ang extension ng file (halimbawa, .EXE) ay hindi ipinapakita, inirerekumenda kong patakbuhin ang Tools -> Folder Options -> Tingnan at alisin ang check sa Itago ang mga extension para sa mga nakarehistrong uri ng file. Pagkatapos ng unang paglunsad ng compiler, dapat na lumitaw ang isang configuration file sa aming folder - FASMW.INI. Buksan ito gamit ang isang karaniwang notepad at magdagdag ng 3 linya sa pinakailalim:

Fasminc=D:\FASM\INCLUDE
Isama=D:\FASM\INCLUDE

Kung na-unpack mo ang FASM sa ibang lokasyon, palitan ang "D:\FASM\" ng iyong path. I-save at isara ang FASMW.INI. Sa hinaharap, maikli kong ipaliwanag kung paano namin gagamitin ang compiler:
1. Sinusulat namin ang text ng program, o binubuksan ang dating nakasulat na text na naka-save sa .asm file, o i-paste ang text ng program mula sa clipboard gamit ang kumbinasyon.
2. Pindutin ang F9 para i-compile at patakbuhin ang program, o Ctrl+F9 para lang mag-compile. Kung ang teksto ng programa ay hindi pa nai-save, hihilingin sa iyo ng compiler na i-save ito bago mag-compile.
3. Kung magsisimula ang programa, sinubukan namin ito para sa tamang operasyon kung hindi, naghahanap kami ng mga error, ang pinakaseryoso kung saan ituturo sa amin ng compiler o banayad na pahiwatig.
Well, ngayon ay maaari na nating simulan ang pinakahihintay na pagsasanay. Inilunsad namin ang aming FASMW.EXE at i-type dito ang code ng aming unang programa:

Isama ang "%fasminc%/win32ax.inc"

Data
Caption db "Aking unang programa.",0
Text db "Hello everyone!",0

Code
simulan:

i-invoke ang ExitProcess,0

I-click ang Run -> Run, o F9 sa keyboard. Sa window ng pag-save, tukuyin ang pangalan ng file at folder na ise-save. Maipapayo na ugaliing i-save ang bawat programa hiwalay na folder, upang hindi malito sa hinaharap, kapag ang bawat programa ay maaaring magkaroon ng isang bungkos ng mga file: mga larawan, mga icon, musika, atbp. Kung ang compiler ay bumubuo ng isang error, maingat na i-double check ang linya na tinukoy nito - marahil ay napalampas mo ang isang kuwit o isang puwang. Kailangan mo ring malaman na ang compiler ay case sensitive, kaya ang .data at .Data ay itinuturing bilang dalawa iba't ibang mga tagubilin. Kung ginawa mo nang tama ang lahat, ang resulta ay isang simpleng MessageBox (Fig. 1). Ngayon, alamin natin kung ano ang isinulat namin sa teksto ng programa. Sa unang linya, na may kasamang direktiba, isinama namin ang malalaking teksto mula sa ilang mga file sa aming programa. Tandaan, sa panahon ng pag-install, sumulat kami ng 3 linya sa FASMO ini-file? Ngayon %fasminc% sa teksto ng programa ay nangangahulugang D:\FASM\INCLUDE o ang landas na iyong tinukoy. Ang kasamang direktiba ay tila ipinapasok sa tinukoy na lugar text mula sa ibang file. Buksan ang WIN32AX.INC file sa include folder gamit ang notepad o sa FASMA mismo at tiyaking awtomatiko naming isinama (naka-attach) sa aming programa ang text mula sa win32a.inc, macro/if.inc, isang grupo ng mga hindi maintindihan (sa ngayon ) mga macro na tagubilin at isang karaniwang hanay ng mga library ng function ng Windows. Sa turn, ang bawat isa sa mga kasamang file ay maaaring maglaman ng higit pang mga kasamang file, at ang chain na ito ay maaaring lumampas sa abot-tanaw. Gamit ang mga kasamang file, nag-aayos kami ng isang uri ng mataas na antas ng wika: upang maiwasan ang nakagawiang paglalarawan ng bawat function nang manu-mano, isinama namin ang buong mga library ng paglalarawan karaniwang mga tampok Windows. Kailangan ba talaga ang lahat ng ito para sa isang maliit na programa? Hindi, ito ay isang bagay tulad ng isang "gentleman's set para sa lahat ng okasyon". Ang mga tunay na hacker, siyempre, ay hindi ikinonekta ang lahat, ngunit kami ay natututo lamang, kaya't mapapatawad para sa amin na gawin ito sa unang pagkakataon.

Susunod mayroon kaming itinalagang seksyon ng data - .data. Sa seksyong ito, ipinapahayag namin ang dalawang variable - Caption at Text. Ang mga ito ay hindi mga espesyal na utos, kaya ang kanilang mga pangalan ay maaaring mapalitan ayon sa gusto mo, kahit na a at b, hangga't walang mga puwang at wala sa Russian. Well, hindi mo maaaring pangalanan ang mga variable nakalaan na salita, halimbawa, code o data, ngunit maaari mong gamitin ang code_ o data1. Ang utos ng db ay nangangahulugang "tukuyin ang byte". Siyempre, ang lahat ng tekstong ito ay hindi magkakasya sa isang byte, dahil ang bawat indibidwal na character ay tumatagal ng isang buong byte. Ngunit sa kasong ito, sa utos na ito, tinukoy lamang namin ang variable ng pointer. Maglalaman ito ng address kung saan nakaimbak ang unang character ng string. Ang teksto ng linya ay ipinahiwatig sa mga panipi, at maaari mong opsyonal na ilagay ang parehong "ganyan" at "ganyan" sa mga panipi - hangga't ang panimulang panipi ay kapareho ng pangwakas. Ang zero pagkatapos ng kuwit ay nagdaragdag ng zero byte sa dulo ng string, na nagpapahiwatig ng dulo ng string (null-terminator). Subukang alisin ang zero na ito kasama ang kuwit sa unang linya at tingnan kung ano ang makukuha mo. Sa pangalawang linya sa partikular na halimbawang ito, magagawa mo nang walang zero (alisin ito kasama ang kuwit - kung hindi man ay magsasaad ang compiler ng error), ngunit gagana lamang ito dahil sa aming halimbawa, ang susunod na seksyon ay magsisimula kaagad pagkatapos ng pangalawa. linya, at bago ito magsimula, ang compiler ay awtomatikong magpasok ng isang grupo ng mga zero na nakahanay sa nakaraang seksyon. Sa pangkalahatan, mga zero sa dulo mga string ng teksto kinakailangan! Susunod na seksyon - seksyon maipapatupad na code mga programa - .code. Sa simula ng seksyon ay may simula: label. Nangangahulugan ito na mula sa puntong ito magsisimulang maisakatuparan ang ating programa. Ang unang command ay ang invoke macroinstruction. Tinatawag nito ang built-in na Windows API function na MessageBox. Ang mga function ng API (application programming interface) ay makabuluhang pinapasimple ang trabaho sa operating system. Para bang hinihiling namin sa operating system na magsagawa ng ilang karaniwang aksyon, at ginagawa ito at pagkatapos ay ibabalik sa amin ang resulta ng gawaing ginawa. Ang pangalan ng function ay sinusundan ng mga parameter nito, na pinaghihiwalay ng mga kuwit. Ang MessageBox function ay may mga sumusunod na parameter:

Ang 1st parameter ay dapat maglaman ng hawakan ng window ng may-ari. Ang hawakan ay parang personal na numero, na inilabas operating system bawat bagay (proseso, window, atbp.). 0 sa aming halimbawa ay nangangahulugan na ang window ay walang may-ari, ito ay nag-iisa at hindi umaasa sa anumang iba pang mga bintana.
Ang 2nd parameter ay isang pointer sa address ng unang titik ng text ng mensahe na nagtatapos sa nabanggit na null terminator. Upang malinaw na maunawaan na ito ay isang address lamang, ilipat natin ang address na ito sa pamamagitan ng 2 byte nang direkta sa function na tawag: i-invoke ang MessageBox,0,Text+2,Caption,MB_OK at siguraduhin na ngayon ang text ay ipapakita nang wala ang unang dalawang titik .
Ika-3 - tagapagpahiwatig ng address ng unang titik ng header ng mensahe.
Ika-4 - istilo ng mensahe. Makakakita ka ng listahan ng mga istilong ito, halimbawa, sa INCLUDE\EQUATES\USER32.INC. Upang gawin ito, mas mabuting gamitin mo ang paghahanap sa Notepad upang mabilis na mahanap ang MB_OK at ang iba pa. Sa kasamaang palad, walang paglalarawan doon, ngunit mula sa pangalan ng estilo ay karaniwan mong mahulaan ang layunin nito. Siyanga pala, ang lahat ng mga istilong ito ay maaaring mapalitan ng isang numerong nagsasaad ng isang istilo o kumbinasyon ng mga ito, halimbawa: MB_OK + MB_ICONEXCLAMATION. USER32.INC ay tumutukoy sa mga halaga ng hexadecimal. Maaari mong gamitin ang mga ito bilang ay o i-convert ang mga ito sa sistemang desimal V engineering mode pamantayan Windows calculator. Kung hindi ka pamilyar sa mga sistema ng numero at hindi alam kung paano naiiba ang decimal sa hexadecimal, mayroon kang 2 pagpipilian: basahin mo ang bagay na ito sa iyong sarili sa Internet/textbook/magtanong sa isang kaibigan, o iwanan ang ideyang ito hanggang sa mas magandang panahon at subukang gawin nang walang impormasyong ito. Dito hindi ako magbibigay ng kahit na maikling impormasyon sa mga sistema ng numero dahil sa katotohanan na kahit na wala ako isang malaking bilang ng mga artikulo at pahina ng anumang naiisip na antas ay isinulat tungkol sa mga ito.

Bumalik tayo sa ating mga tupa. Ang ilang mga istilo ay hindi maaaring gamitin nang sabay - halimbawa, MB_OKCANCEL at MB_YESNO. Ang dahilan ay ang kabuuan ng mga ito mga numerong halaga(1+4=5) ay tutugma sa halaga ng isa pang istilo - MB_RETRYCANCEL. Ngayon mag-eksperimento sa mga parameter ng function upang magsanay sa pag-secure ng materyal, at magpapatuloy kami. Ang MessageBox function ay naka-pause sa pagpapatupad ng program at naghihintay para sa pagkilos ng user. Sa pagkumpleto, ibabalik ng function ang resulta ng pagkilos ng user sa program, at patuloy na gumagana ang program. Ang pagtawag sa ExitProcess function ay nagtatapos sa proseso ng aming programa. Ang function na ito ay may isang parameter lamang - ang exit code. Karaniwan, kung normal na lumabas ang program, ang code na ito katumbas ng zero. Para mas maintindihan huling linya ang aming code - .end start, - maingat na pag-aralan ang katumbas na code: format PE GUI 4.0

isama ang "%fasminc%/win32a.inc"

seksyong ".data" na nababasang data na maaaring isulat

Caption db "Ang aming unang programa.",0
Text db "Madali ang FASM assembler!",0

seksyong ".code" na nababasa na code na maipapatupad
simulan:
tawagan ang MessageBox,0,Text,Caption,MB_OK
i-invoke ang ExitProcess,0

seksyong ".idata" import data na nababasa na nasusulat
library KERNEL32, "KERNEL32.DLL",\
USER32, "USER32.DLL"

import KERNEL32,\
ExitProcess, "ExitProcess"

import USER32,\
MessageBox, "MessageBoxA"

Para sa compiler ito ay halos magkapareho sa nakaraang halimbawa, ngunit para sa amin ang tekstong ito ay mukhang ibang programa. Partikular kong ibinigay ang pangalawang halimbawang ito upang sa simula pa lang ay magkaroon ka ng ideya sa paggamit ng mga macroinstructions at mula ngayon ay maaari mong, lumipat mula sa isang konektadong file patungo sa isa pa, malayang makapunta sa totoong code ng program na nakatago sa ilalim ng belo ng macros. Subukan nating maunawaan ang mga pagkakaiba. Ang pinakauna, hindi masyadong kapansin-pansin, ngunit karapat-dapat espesyal na atensyon- ito ang ikinonekta namin sa teksto ng programa hindi win32ax, ngunit win32a lamang. Inabandona namin ang isang malaking set at nilimitahan namin ang aming sarili sa isang maliit. Susubukan naming gawin nang hindi ikinokonekta ang lahat mula sa win32ax, bagama't kakailanganin pa rin namin ang ilan dito sa ngayon. Samakatuwid, ayon sa mga macro mula sa win32ax, manu-mano kaming sumulat ng ilang mga kahulugan. Halimbawa, isang macro mula sa isang win32ax file:
macro .data ( section ".data" data readable writeable )

sa panahon ng compilation, awtomatikong pinapalitan ang .data ng seksyong ".data" na nababasang data na nababasa. Dahil hindi namin isinama ang macro na ito sa teksto ng programa, kailangan namin itong isulat mismo detalyadong kahulugan mga seksyon. Sa pamamagitan ng pagkakatulad, mahahanap mo ang mga dahilan para sa natitirang mga pagbabago sa teksto ng programa sa pangalawang halimbawa. Tinutulungan ka ng mga macro na maiwasan ang regular na pagsusulat malalaking programa. Samakatuwid, kailangan mo lang silang masanay kaagad, at mamahalin mo sila mamaya =). Subukang alamin ang mga pagkakaiba sa pagitan ng una at pangalawang halimbawa sa iyong sarili, gamit ang teksto ng mga macro na ginamit sa win32ax. Sabihin ko lang na maaari mong tukuyin ang anumang iba pang pangalan ng data o seksyon ng code sa mga quote - halimbawa: seksyong "virus" na nababasa na code na maipapatupad. Ito ay pangalan lamang ng seksyon at hindi isang utos o pahayag. Kung naiintindihan mo ang lahat, maaari mo nang isulat ang iyong sariling virus. Maniwala ka sa akin, ito ay napakadali. Baguhin lamang ang pamagat at teksto ng mensahe:
Caption db "Mapanganib na Virus.",0

Text db "Hello, isa akong partikular na mapanganib na Trojan virus at kumakalat ako sa Internet.",13,\
"Dahil ang aking may-akda ay hindi marunong magsulat ng mga virus na nagdudulot ng pinsala, dapat mo akong tulungan.",13,\
"Mangyaring gawin ang sumusunod:",13,\
"1. Burahin ang mga direktoryo ng C:\Windows at C:\Program files sa iyong disk",13,\
"2. Ipadala ang file na ito sa lahat ng iyong mga kaibigan",13,\
"Salamat nang maaga.",0

Ang numero 13 ay ang code para sa carriage return character sa mga Microsoft system. Ang \ sign ay ginagamit sa FASM syntax upang pagsamahin ang maramihang mga linya sa isa, ang linya ay magiging masyadong mahaba at lumalabas sa gilid ng screen. Halimbawa, maaari naming isulat ang start:, o maaari rin naming isulat ang st\
ar\
t:

Hindi mapapansin ng compiler ang pagkakaiba sa pagitan ng una at pangalawang opsyon.
Buweno, para mas maging masaya ang ating "virus", maaari mong palitan ang MB_OK ng MB_ICONHAND o simpleng numero 16. Sa kasong ito, ang window ay magkakaroon ng istilo ng mensahe ng error at magbubunga ng mas kahanga-hangang epekto sa biktima ng ang "impeksyon" (Larawan 2).

Iyon lang para sa araw na ito. Nais kong tagumpay ka at makita kang muli!
Ang lahat ng mga halimbawang ibinigay ay nasubok upang gumana nang tama sa ilalim ng Windows XP at malamang na gagana sa ilalim ng iba pang mga bersyon ng Windows, ngunit hindi ako gumagawa ng mga garantiya na gagana ang mga ito nang tama sa iyong computer. Pinagmulan ng mga teksto mga program na mahahanap mo sa forum.

Pagprograma ng wika ng assembly

Ang bahaging ito ng kurso ay sumasaklaw sa mga pangunahing kaalaman sa programming language ng pagpupulong para sa arkitektura ng Win32.

Ang lahat ng mga proseso sa makina sa pinakamababang antas ng hardware ay hinihimok lamang ng mga utos (mga tagubilin) wika ng makina. Ang assembly language ay isang simbolikong representasyon ng machine language. Binibigyang-daan ka ng Assembly language na magsulat ng maikli at mabilis na mga programa. Gayunpaman, ang prosesong ito ay lubhang matrabaho. Para sa pagsusulat hangga't maaari epektibong programa kailangan magandang kaalaman mga tampok ng mga utos ng wikang pagpupulong, atensyon at katumpakan. Samakatuwid, sa katotohanan, ang pangunahing mga programa ay nakasulat sa wikang pagpupulong na dapat magbigay mahusay na trabaho may hardware. Gayundin, ang mga seksyon ng programa na kritikal sa mga tuntunin ng oras ng pagpapatupad o pagkonsumo ng memorya ay nakasulat sa wika ng pagpupulong. Kasunod nito, ang mga ito ay pormal sa anyo ng mga subroutine at pinagsama sa code sa isang mataas na antas ng wika.

1. Nagrerehistro

Ang mga rehistro ay mga espesyal na memory cell na matatagpuan nang direkta sa processor. Ang pagtatrabaho sa mga rehistro ay mas mabilis kaysa sa pagtatrabaho sa mga cell RAM, samakatuwid, ang mga rehistro ay aktibong ginagamit kapwa sa mga programa ng wikang pagpupulong at sa mga compiler ng mataas na antas ng wika.

Ang mga rehistro ay maaaring nahahati sa pangkalahatang layunin na mga rehistro,index ng command,rehistro ng bandila at mga rehistro ng segment.

1.1. Mga rehistro ng pangkalahatang layunin

SA Ang mga rehistro ng pangkalahatang layunin ay isang pangkat ng 8 mga rehistro na maaaring magamit sa isang programa ng wika ng pagpupulong. Ang lahat ng mga rehistro ay 32 bits ang laki at maaaring hatiin sa 2 o higit pang mga bahagi.

Tulad ng makikita mula sa figure, ang ESI, EDI, ESP at EBP registers ay nagbibigay-daan sa iyo na ma-access ang mas mababang 16 bits sa pamamagitan ng mga pangalan na SI, DI, SP at BP, ayon sa pagkakabanggit, at ang EAX, EBX, ECX at EDX registers ay nagpapahintulot sa iyo na i-access ang parehong mas mababang 16 bits (sa mga pangalan AX , BX, CX at DX), at sa dalawang mababang byte nang hiwalay (pinangalanang AH/AL, BH/BL, CH/CL at

Ang mga pangalan ng mga rehistro ay nagmula sa kanilang layunin:

EAX/AX/AH/AL (accumulator register) – baterya;

EBX/BX/BH/BL (base register) – base register;

ECX/CX/CH/CL (counter register) – counter;

EDX/DX/DH/DL (data register) – rehistro ng data;

ESI/SI (pinagmulan rehistro ng index) – source index;

EDI/DI (destination index register) – index ng receiver (recipient);

ESP/SP (stack pointer register) – stack pointer register;

EBP/BP (base pointer register) – stack frame base pointer register.

Sa kabila ng umiiral na espesyalisasyon, lahat ng mga rehistro ay maaaring gamitin sa anumang pagpapatakbo ng makina. Gayunpaman, dapat nating isaalang-alang ang katotohanan na ang ilang mga tagubilin ay gumagana lamang sa ilang mga rehistro. Halimbawa, ginagamit ng mga tagubilin sa multiplikasyon at paghahati ang mga rehistro ng EAX at EDX upang iimbak ang pinagmulang data at ang resulta ng operasyon. Ginagamit ng mga tagubilin ng loop control ang ECX register bilang loop counter.

Ang isa pang nuance ay ang paggamit ng mga rehistro bilang base, i.e. Imbakan ng address ng RAM. Ang anumang mga rehistro ay maaaring gamitin bilang mga base na rehistro, ngunit ipinapayong gumamit ng mga rehistro ng EBX, ESI, EDI o EBP. Sa kasong ito, ang laki ng command ng makina ay karaniwang mas maliit.

Sa kasamaang palad, ang bilang ng mga rehistro ay napakaliit, at kadalasan ay mahirap matukoy kung paano mahusay na gamitin ang mga ito.

1.2. Index ng Command

EIP register ( index ng command) ay naglalaman ng offset ng susunod na utos na isasagawa. Ang rehistrong ito ay hindi direktang naa-access sa programmer, ngunit ang halaga nito ay na-load at binago ng iba't ibang mga control command, na kinabibilangan ng mga command ng conditional at unconditional jumps, calling procedures at pagbabalik mula sa procedures.

1.3. Pagrehistro ng bandila

Ang flag ay medyo kumukuha ng value 1 (“flag set”) kung matugunan ang ilang kundisyon, at ang value na 0 (“flag clear”) kung hindi. Ang processor ay may rehistro ng mga flag na naglalaman ng isang hanay ng mga flag na nagpapakita ng kasalukuyang estado ng processor.

Pagtatalaga

Pangalan

Inilipat ang bandila

Nakareserba

Bandila ng parity

Nakareserba

Auxiliary Carry Flag

Pantulong

Nakareserba

Walang bandila

Tanda ng bandila

Tagasubaybay ng bandila

Interrupt Enable Flag

Flag ng pahintulot

I-flag ang mga direksyon

Repo bandila

Antas ng Pribilehiyo ng I/O

Antas sa

Naka-nest ang bandila

Nakareserba

Ipinagpatuloy ang bandila

Virtual-8086 Mode

Virtual mode

Sinusuri ka

Flag ng Virtual Interrupt

Virtual

Nakabinbin ang Virtual Interrupt

Naghihintay

Suriin para sa

Nakareserba

Ang halaga ng mga flag na CF, DF at IF ay maaaring direktang baguhin sa rehistro ng bandila gamit mga espesyal na tagubilin(hal. CLD upang i-reset ang flag ng direksyon), ngunit walang mga tagubilin na nagpapahintulot sa iyo na ma-access ang rehistro ng mga flag na parang ito ay isang regular na rehistro. Gayunpaman, maaari kang makatipid

ang rehistro ng bandila sa stack o ang rehistro ng AH at ibalik ang rehistro ng bandila mula sa kanila gamit ang mga tagubiling LAHF, SAHF, PUSHF, PUSHFD, POPF at POPFD.

1.3.1. Mga Flag ng Katayuan

Ang mga flag ng status (bits 0, 2, 4, 6, 7 at 11) ay nagpapakita ng resulta ng mga tagubilin sa aritmetika gaya ng ADD,SUB,MUL,DIV.

Ang carry flag CF ay nakatakda kapag nagdadala mula sa isang senior makabuluhang bit/hiram sa pinaka makabuluhang bit at nagpapahiwatig ng pagkakaroon ng overflow sa unsigned integer arithmetic. Ginagamit din sa mahabang arithmetic.

Ang parity flag na PF ay nakatakda kung ang hindi bababa sa makabuluhang byte ng resulta ay naglalaman ng kahit na bilang ng isang bit. Sa una, ang watawat na ito ay inilaan para gamitin sa mga programa sa komunikasyon: Kapag nagpapadala ng data sa mga linya ng komunikasyon, maaari ding magpadala ng parity bit para sa kontrol at ang mga tagubilin para sa pagsuri sa parity flag ay naging mas madali upang suriin ang integridad ng data.

Auxiliary Carry Flag Nakatakda ang AF kapag nagdadala mula sa bit ika-3 resulta/loan in ika-3 bit ng resulta. Ang watawat na ito ay inilaan para sa paggamit sa BCD (binary coded decimal, BCD) arithmetic.

Ang ZF zero flag ay nakatakda kung ang resulta ay zero.

Ang sign flag na SF ay katumbas ng halaga ng pinaka makabuluhang bit ng resulta, na siyang sign bit sa signed arithmetic.

Overflow flag Ang OF ay nakatakda kung ang resulta ng integer ay masyadong mahaba upang magkasya sa target na operand (rehistro o lokasyon ng memorya). Ang flag na ito ay nagpapahiwatig ng pagkakaroon ng overflow sa signed integer arithmetic.

Sa mga flag na ito, ang CF flag lang ang maaaring direktang baguhin gamit ang mga tagubilin ng STC, CLC, at CMC.

Ang mga flag ng status ay nagbibigay-daan sa parehong pagtuturo ng aritmetika na mag-isyu resulta ng tatlo iba't ibang uri: Unsigned, signed at binary coded decimal (BCD) integer. Kung ang resulta ay itinuturing na isang hindi pirmadong numero, ang CF flag ay nagpapakita ng overflow na kundisyon (carry o borrow), para sa isang nilagdaang resulta, ang carry o borrow ay nagpapakita ng OF flag, at para sa isang BCD na resulta, ang isang carry/lorrow ay nagpapakita ng AF bandila. Ang watawat ng SF ay sumasalamin sa tanda ng isang nilagdaang resulta, ang watawat ng ZF ay sumasalamin sa parehong hindi nilagdaan at isang nilagdaang null na resulta.

Sa long integer arithmetic, ang CF flag ay ginagamit kasabay ng add with carry (ADC) at subtract with borrow (SBB) na mga tagubilin upang magpalaganap ng carry o humiram mula sa isang nakalkulang digit ng mahabang numero patungo sa isa pa.

Mga tagubilin

may kondisyon

transition Jcc (transition

kundisyon cc ), SETcc (set

ibig sabihin

byte ng resulta

dependencies

kundisyon cc ),LOOPcc (organisasyon

at CMOVcc (conditional

pagkopya)

gamitin

isa o higit pa

mga flag ng katayuan upang suriin ang kundisyon. Halimbawa, ang JLE jump instruction (jump kung mas kaunti o katumbas) ay nagsusuri sa kondisyong “ZF = 1 o SF ≠ OF”.

Ang bandila ng PF ay ipinakilala para sa pagiging tugma sa iba pang mga arkitektura ng microprocessor at bihirang ginagamit para sa layunin nito. Ang mas karaniwang paggamit nito ay kasabay ng iba pang mga flag ng status sa floating-point arithmetic: mga tagubilin sa paghahambing (FCOM, FCOMP, atbp.) sa math coprocessor set condition flags C0, C1, C2 at C3 sa loob nito, at ang mga flag na ito ay maaaring kopyahin para mag-flag register. Upang gawin ito, inirerekumenda na gamitin ang pagtuturo ng FSTSW AX upang iimbak ang salita ng katayuan ng coprocessor sa rehistro ng AX at ang pagtuturo ng SAHF upang kasunod na kopyahin ang mga nilalaman ng rehistro ng AH sa mababang 8 bits ng rehistro ng bandila, na nagtatapos sa C0. sa CF flag, C2 sa PF flag, at C3 sa ZF flag. Ang C2 flag ay nakatakda, halimbawa, sa kaso ng mga walang kapantay na argumento (NaN o hindi sinusuportahang format) sa pagtuturo ng paghahambing ng FUCOM.

1.3.2. Kontrolin ang bandila

Bandila ng direksyon Kinokontrol ng DF (bit 10 sa rehistro ng mga flag) ang mga tagubilin sa string (MOVS, CMPS, SCAS, LODS at STOS) - ang pagtatakda ng bandila ay nagiging sanhi ng pagbawas ng mga address (pagproseso ng mga linya mula sa matataas hanggang sa mababang mga address), ang pag-zero ay nagiging sanhi ng pagtaas ng mga address. Ang mga tagubilin sa STD at CLD ay itinakda at i-clear ang flag ng DF ayon sa pagkakabanggit.

1.3.3. Mga Flag ng System at Field ng IOPL

Kinokontrol ng mga flag ng system at field ng IOPL ang operating environment at hindi nilayon para sa paggamit ng mga application program.

Interrupt enable ang flag IF—pag-clear sa flag na ito ay nagbabawal sa pagtugon sa mga naka-mask na kahilingan sa interrupt.

Bandila ng bakas TF – pinahihintulutan ng pagtatakda ng flag na ito hakbang-hakbang na mode pag-debug, kapag matapos ang bawat makumpleto

mga tagubilin, ang programa ay naaantala at isang espesyal na tagapangasiwa ng interrupt ay tinatawag.

Ipinapakita ng field ng IOPL ang antas ng priyoridad ng I/O maipapatupad na programa o mga gawain: upang ang isang programa o gawain ay makapagsagawa ng mga tagubilin sa I/O o magpalit ng isang IF flag, nito kasalukuyang antas ang priority (CPL) ay dapat na ≤ IOPL.

Task nesting flag NT – ang watawat na ito ay itinakda kapag ang kasalukuyang gawain ay "naka-nest" sa isa pa, nagambalang gawain, at ang TSS na bahagi ng estado ng kasalukuyang gawain ay nagbibigay puna kasama ang TSS ng nakaraang gawain. Ang bandila ng NT ay sinusuri ng tagubilin ng IRET upang matukoy kung ang pagbabalik ay intertask o intratask.

Ipagpatuloy ang bandila Ginagamit ang RF upang i-mask ang mga error sa pag-debug.

VM - Ang pagtatakda ng flag na ito sa protected mode ay nagdudulot ng paglipat sa virtual 8086 mode.

Flag ng check ng pagkakahanay AC - ang pagtatakda ng flag na ito kasama ang AM bit sa CR0 register ay nagbibigay-daan sa kontrol sa pag-align ng operand kapag ina-access ang memory: ang pag-access sa isang hindi nakahanay na operand ay nagdudulot ng pagbubukod.

VIF – virtual na kopya ng bandila ng IF; ginamit kasabay ng bandila ng VIP.

VIP – nakatakdang ipahiwatig ang pagkakaroon ng nakabinbing interrupt.

ID - Ang kakayahang baguhin ang flag na ito gamit ang program sa rehistro ng mga flag ay nagpapahiwatig ng suporta para sa pagtuturo ng CPUID.

1.4. Mga rehistro ng segment

Ang processor ay may 6 na tinatawag na segment registers: CS, DS, SS, ES, FS at GS. Ang kanilang pag-iral ay dahil sa mga detalye ng organisasyon at paggamit ng RAM.

Ang 16-bit na mga rehistro ay maaari lamang tumugon sa 64 KB ng RAM, na malinaw na hindi sapat para sa isang mas marami o mas kaunting disenteng programa. Samakatuwid, ang memorya ay inilalaan sa programa sa anyo ng ilang mga segment, na may sukat na 64 KB. Kasabay nito, ang mga ganap na address ay 20-bit, na naging posible upang matugunan ang 1 MB ng RAM. Ang tanong ay lumitaw: paano ka makakapag-imbak ng 20-bit na mga address na may 16-bit na mga rehistro? Upang malutas ang problemang ito, hinati ang address sa offset. Ang base ay ang address ng simula ng segment, at ang offset ay ang byte number sa loob ng segment. Ang isang paghihigpit ay ipinataw sa address ng simula ng segment - ito ay dapat na isang maramihang ng 16. Sa kasong ito, ang huling 4 na bit ay katumbas ng 0 at hindi nakaimbak, ngunit ipinahiwatig. Kaya, dalawang 16-bit na bahagi ng address ang nakuha. Upang makatanggap

apat na ganap na address ang idinagdag sa database zero bits, at ang nagresultang halaga ay idinagdag kasama ang offset.

Ginamit ang mga rehistro ng segment upang iimbak ang address ng simula ng segment ng code (CS - segment ng code), segment ng data (DS - segment ng data) at segment ng stack (SS - segment ng stack). Ang mga rehistro ng ES, FS at GS ay idinagdag sa ibang pagkakataon. Mayroong ilang mga modelo ng memorya, bawat isa ay nagsasangkot ng paglalaan ng isa o higit pang mga segment ng code at isa o higit pang mga segment ng data sa isang programa: maliit, maliit, katamtaman, compact, malaki, at malaki. Mayroong ilang partikular na mga kombensiyon para sa mga tagubilin sa wika ng pagpupulong: ang mga jump address ay na-segment ng CS register, ang mga access sa data ay na-segment ng DS register, at ang mga stack access ay na-segment ng SS register. Kung ang isang programa ay inilaan ng ilang mga segment para sa code o data, ang mga halaga sa CS at DS registers ay kailangang baguhin upang ma-access ang ibang segment. May mga tinatawag na "malapit" at "malayo" na mga transition. Kung ang utos kung saan kailangang gawin ang paglipat ay nasa parehong segment, kung gayon sa paglipat ay sapat na upang baguhin lamang ang halaga ng rehistro ng IP. Ang nasabing paglipat ay tinawag na malapit. Kung ang utos kung saan dapat gawin ang paglipat ay nasa ibang segment, kung gayon upang lumipat ay kinakailangan na baguhin ang parehong halaga ng rehistro ng CS at ang halaga ng rehistro ng IP. Ang nasabing paglipat ay tinatawag na long-distance at mas tumagal.

Pinapayagan ka ng 32-bit na mga rehistro na tugunan ang 4 GB ng memorya, na sapat na para sa anumang programa. Ang Windows ay nagpapatakbo ng bawat Win32 program sa isang hiwalay na virtual space. Nangangahulugan ito na ang bawat programa ng Win32 ay magkakaroon ng 4 GB address space, ngunit hindi nangangahulugan na ang bawat programa ay may 4 GB pisikal na memorya, ngunit tanging ang program ay makaka-access ng anumang address sa loob ng mga limitasyong ito. At gagawin ng Windows ang lahat ng kailangan upang matiyak na ang memorya na ina-access ng program ay "umiiral." Siyempre, ang programa ay dapat sumunod sa mga patakarang itinatag

Windows, kung hindi, isang error sa General Protection Fault ang nangyayari.

Sa ilalim ng arkitektura ng Win32, hindi na kailangang paghiwalayin ang address sa base at offset, at ang pangangailangan para sa mga modelo ng memorya. Sa 32-

ay ginagamit sa ibang paraan1. Dati, kinakailangang iugnay ang mga indibidwal na bahagi ng programa sa isa o ibang rehistro ng segment at i-save/ibalik ang rehistro ng DS kapag lumipat sa isa pang segment ng data o tahasang i-segment ang data sa isa pang rehistro. Sa isang 32-bit na arkitektura, hindi na ito kinakailangan, at sa pinakasimpleng kaso maaari mong kalimutan ang tungkol sa mga rehistro ng segment.

1.5. Gamit ang isang stack

Ang bawat programa ay may isang lugar ng memorya na tinatawag na stack. Ang stack ay ginagamit upang ipasa ang mga parameter sa mga pamamaraan at upang mag-imbak ng lokal na data ng pamamaraan. Tulad ng alam mo, ang stack ay isang lugar ng memorya, kapag nagtatrabaho kung saan kinakailangan na sundin ang ilang mga patakaran, lalo na: ang data na unang pumasok sa stack ay tinanggal mula doon sa huli. Sa kabilang banda, kung ang programa ay inilalaan ng ilang memorya, pagkatapos ay walang mga pisikal na paghihigpit sa pagbabasa at pagsulat. Paano pinagkakasundo ang dalawang magkasalungat na prinsipyong ito?

Magkaroon tayo ng isang function na f1 na tumatawag sa function na f2, at ang function na f2, naman, ay tumatawag sa function na f3. Kapag tinawag ang function na f1, inilalaan ito ng isang tiyak na espasyo sa stack para sa lokal na data. Ang puwang na ito ay inilalaan sa pamamagitan ng pagbabawas mula sa rehistro ng ESP ng isang halaga na katumbas ng laki ng kinakailangang memorya. Minimum na sukat ang inilalaang memorya ay 4 bytes, i.e. kahit na ang isang pamamaraan ay nangangailangan ng 1 byte, dapat itong tumagal ng 4 na byte.

Ang function na f1 ay nagsasagawa ng ilang mga aksyon at pagkatapos ay tumatawag

Tinatawag ng function na f2 ang function na f3, na naglalaan din ng espasyo sa stack. Ang function na f3 ay hindi tumatawag sa iba pang mga function at, sa pagkumpleto, dapat magbakante ng espasyo sa stack sa pamamagitan ng pagdaragdag sa ESP register ang halaga na ibinawas noong tinawag ang function. Kung ang function na f3 ay hindi naibalik ang halaga ng rehistro ng ESP, pagkatapos ay ang function na f2, na nagpapatuloy sa trabaho nito, ay hindi maa-access ang sarili nitong data, dahil hinahanap niya

na bago ang kanyang tawag.

Kaya, sa antas ng pamamaraan, kinakailangang sundin ang mga patakaran para sa pagtatrabaho sa stack - ang pamamaraan na tumagal ng puwang sa huling stack ay dapat munang palayain ito. Kung hindi susundin ang panuntunang ito, hindi gagana nang tama ang programa. Ngunit maaaring ma-access ng bawat pamamaraan ang stack area nito sa anumang paraan. Kung mapipilitan kaming sundin ang mga patakaran para sa pagtatrabaho sa stack sa loob ng bawat pamamaraan, kailangan naming ilipat ang data mula sa stack patungo sa isa pang lugar ng memorya, at ito ay magiging lubhang hindi maginhawa at lubos na magpapabagal sa pagpapatupad. ng programa.

Ang bawat programa ay may lugar ng data kung saan matatagpuan ang mga global variable. Bakit nakaimbak ang lokal na data sa stack? Ginagawa ito upang mabawasan ang dami ng memorya na inookupahan ng programa. Kung ang programa ay sunud-sunod tumawag ng ilang mga pamamaraan, pagkatapos ay sa bawat sandali ng oras magkakaroon ng puwang na inilalaan lamang para sa data ng isang pamamaraan, dahil Ang stack ay inookupahan at napalaya. Umiiral ang lugar ng data hangga't tumatakbo ang program. Kung ang lokal na data ay matatagpuan sa lugar ng data, ang espasyo ay kailangang ilaan para sa lokal na data para sa lahat ng mga pamamaraan ng programa.

Ang lokal na data ay hindi awtomatikong sinisimulan. Kung sa halimbawa sa itaas, ang function na f2 pagkatapos ng function na f3 ay tumatawag sa function na f4, pagkatapos ay ang function na f4 ay magaganap sa stack na dating inookupahan ng function na f3, kaya ang function na f4 ay "magmana" ng data ng function na f3. Samakatuwid, dapat pangalagaan ng bawat pamamaraan ang pagsisimula ng lokal na data nito.

2. Pangunahing konsepto ng wikang pagpupulong

2.1. Mga identifier

Ang konsepto ng isang identifier sa assembly language ay hindi naiiba sa konsepto ng isang identifier sa ibang mga wika. Maaari kang gumamit ng mga letrang Latin, numero at _ na palatandaan. ? @ $ , at ang tuldok ay maaari lamang maging unang character ng identifier. Ang malaki at maliit na titik ay itinuturing na katumbas.

2.2. Mga integer

SA Sa isang programa sa wika ng pagpupulong, ang mga integer ay maaaring isulat sa binary, octal, decimal, at hexadecimal system Pagtutuos Upang tukuyin ang sistema ng numero sa dulo ng isang numero