{"id":143,"date":"2018-03-11T20:55:18","date_gmt":"2018-03-11T19:55:18","guid":{"rendered":"http:\/\/www.kompikownia.pl\/?p=143"},"modified":"2019-03-07T23:18:57","modified_gmt":"2019-03-07T22:18:57","slug":"asembler-rtdsc-i-wlasny-benchmark-architektura-systemow-komputerowych","status":"publish","type":"post","link":"https:\/\/www.kompikownia.pl\/index.php\/2018\/03\/11\/asembler-rtdsc-i-wlasny-benchmark-architektura-systemow-komputerowych\/","title":{"rendered":"Asembler, RDTSC i w\u0142asny benchmark &#8211; Architektura System\u00f3w Komputerowych"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Czas czytania:<\/span> <span class=\"rt-time\">6<\/span> <span class=\"rt-label rt-postfix\">minut<\/span><\/span><p>Dzisiaj zajmiemy si\u0119 asemblerem w zakresie wymaganym na laboratoriach z &#8222;Architektura System\u00f3w Komputerowych&#8221;.<\/p>\n<p>Zanim zaczniemy, musimy pozna\u0107 kilka podstawowych poj\u0119\u0107. Musimy dowiedzie\u0107 si\u0119 mi\u0119dzy innymi, czym s\u0105 rejestry. Powinni\u015bmy tak\u017ce zna\u0107 kilka podstawowych komend. Ale nie przejmuj si\u0119, nie ma ich wiele \ud83d\ude42<\/p>\n<p>Prze\u0107wicz dok\u0142adnie to, co poni\u017cej zosta\u0142o opisane. Kr\u0105\u017c\u0105 wie\u015bci, \u017ce Architektura System\u00f3w Komputerowych to przedmiot, kt\u00f3ry jest najlepszym przesiewem \ud83d\ude42<\/p>\n<h1>Podstawowe poj\u0119cia<\/h1>\n<p>B\u0119dziemy operowali na <strong>rejestrach. <\/strong>Czym jest rejestr? Jest to najszybsza, ale i\u00a0najmniejsza pami\u0119\u0107 jak\u0105 dysponuje procesor. W procesorach x86 wyst\u0119puje stosunkowo ma\u0142o rejestr\u00f3w. Oto one:<\/p>\n<ul>\n<li><strong>EAX \u2013 <\/strong>akumulator \u2013 u\u017cywany do przechowywania wynik\u00f3w wielu operacji<\/li>\n<li><strong>EBX \u2013 <\/strong>rejestr bazowy \u2013 s\u0142u\u017cy do adresowania<\/li>\n<li><strong>ECX \u2013 <\/strong>rejestr licznikowy \u2013 s\u0142u\u017cy jako licznik w p\u0119tli<\/li>\n<li><strong>EDX \u2013 <\/strong>rejestr danych \u2013 umo\u017cliwia przekaz\/odbi\u00f3r danych z port\u00f3w we\/wy<\/li>\n<li><strong>ESP \u2013 <\/strong>wska\u017anik wierzcho\u0142ka stosu<\/li>\n<li><strong>EBP \u2013 <\/strong>rejestr bazowy \u2013 s\u0142u\u017cy do adresowania<\/li>\n<li><strong>ESI \u2013 <\/strong>rejestr \u017ar\u00f3d\u0142owy \u2013 trzyma \u017ar\u00f3d\u0142o \u0142a\u0144cucha danych<\/li>\n<li><strong>EDI \u2013 <\/strong>rejestr przeznaczenia \u2013 przetrzymuje informacje o miejscu docelowym \u0142a\u0144cucha danych<\/li>\n<\/ul>\n<p>Wszystkie powy\u017csze rejestry s\u0105 32 bitowe. S\u0105 to rejestry og\u00f3lnego przeznaczenia. Oznacza to, \u017ce nie musimy ich wykorzystywa\u0107 koniecznie do tego, do czego z regu\u0142y s\u0105 u\u017cywane. Wszystko zale\u017cy tylko od ciebie.<\/p>\n<p>Warto wspomnie\u0107 tak\u017ce o rejestrze <strong>EIP. <\/strong>W przeciwie\u0144stwie do powy\u017cszych, nie jest to rejestr og\u00f3lnego przeznaczenia. W EIP zawsze przechowywany jest adres aktualnie wykonywanej instrukcji kodu.<\/p>\n<h1>Podstawowy zestaw narz\u0119dzi<\/h1>\n<p>Do naszych analiz u\u017cyjemy programu OllyDbg. (Do \u015bci\u0105gni\u0119cia wraz z odpowiednimi plikami \u2013 (b\u0119dzie dost\u0119pne p\u00f3\u017aniej). W paczce razem z OllyDbg znajduje si\u0119 program test.exe, kt\u00f3ry b\u0119dziemy \u201emodyfikowali\u201d. Na jego przyk\u0142adzie b\u0119dziemy obserwowali prac\u0119 procesora podczas wykonywania r\u00f3\u017cnych instrukcji.<\/p>\n<figure id=\"attachment_150\" aria-describedby=\"caption-attachment-150\" style=\"width: 893px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-150 size-full\" src=\"https:\/\/www.kompikownia.pl\/wp-content\/uploads\/2018\/03\/z1.png\" alt=\"Okno programu Ollydbg\" width=\"893\" height=\"622\" \/><figcaption id=\"caption-attachment-150\" class=\"wp-caption-text\">Okno programu ollydbg<\/figcaption><\/figure>\n<p>Po otworzeniu programu OllyDbg uka\u017ce nam si\u0119 widok taki jak na powy\u017cszym zrzucie ekranu. Aby\u015bmy mogli otworzy\u0107 interesuj\u0105cy nas plik, musimy klikn\u0105\u0107 File-&gt;Open. Nast\u0119pnie wybieramy test.exe<\/p>\n<p><strong>UWAGA! Je\u017celi na g\u00f3rnej belce pisze ci: module ntdll, to kliknij View-&gt;Executable Modules. W nowo utworzonym oknie wybierz modu\u0142, na kt\u00f3rym b\u0119dziemy operowali (test)<\/strong><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-151 size-full\" src=\"https:\/\/www.kompikownia.pl\/wp-content\/uploads\/2018\/03\/z2.png\" alt=\"\" width=\"982\" height=\"524\" \/><\/p>\n<p>Ten widok mo\u017ce ci\u0119 przerazi\u0107 \u2026 O co tu w og\u00f3le chodzi? Ju\u017c wyja\u015bniam J<\/p>\n<p>Wi\u0119ksz\u0105 cz\u0119\u015b\u0107 okna programu zajmuj\u0105 instrukcj\u0119, kt\u00f3re zawiera nasz program. To, o czym m\u00f3wi\u0119, kryje si\u0119 pod cyferk\u0105 1. Pod cyferk\u0105 2 natomiast znajduj\u0105 si\u0119 omawiane wcze\u015bniej rejestry procesora \u2013 a konkretnie \u2013 ich zawarto\u015b\u0107. Ta cz\u0119\u015b\u0107 okna przykuje nasz\u0105 g\u0142\u00f3wn\u0105 uwag\u0119.<\/p>\n<p>Pod tr\u00f3jeczk\u0105 kryje si\u0119 zawarto\u015b\u0107 pami\u0119ci RAM, kt\u00f3ra zosta\u0142a przydzielona na poczet naszego programu.<\/p>\n<p>Zanim zaczniemy cokolwiek robi\u0107, poznajmy kilka instrukcji asemblerowych, kt\u00f3re przydadz\u0105 si\u0119 w przysz\u0142o\u015bci.<\/p>\n<h1>Podstawowe instrukcje asemblera<\/h1>\n<p><strong>mov cel, zrodlo \u2013 <\/strong>przenosi zawarto\u015b\u0107 zrodlo do cel<br \/>\n<strong>jmp adres <\/strong>\u2013 wykonuje bezwarunkowy skok do miejsca okre\u015blonego jako operand tego rozkazu. Rozkaz JMP zmienia zawarto\u015b\u0107 PC (Program Counter) czyli rejestru EIP.<br \/>\n<strong>sub cel,zrodlo\u2013 <\/strong>wykonuje odejmowanie \u017ar\u00f3d\u0142a od celu i wynik zapisuje w cel.<br \/>\n<strong>sbb cel,zrodlo\u2013 <\/strong>wykonuje odejmowanie z przeniesieniem. (Cel=\u017ar\u00f3d\u0142o-cel)<br \/>\n<strong>rdtsc\u2013 <\/strong>wynikiem jest 64 bitowa liczba, kt\u00f3ra zawiera ilo\u015b\u0107 cykli procesora od uruchomienia komputera. Cz\u0119\u015bci liczby s\u0105 zapisane w rejestrach EDX (starsza cz\u0119\u015b\u0107) \u00a0i EAX (m\u0142odsza cz\u0119\u015b\u0107).<\/p>\n<h1>\u00a0Pierwszy program<\/h1>\n<p>Skoro znamy podstawowe instrukcje asemblera, to rozpocznijmy analiz\u0119 najprostszego mo\u017cliwego programu:<\/p>\n<pre lang=\"asm\">mov eax, 100\nmov eax, 300\nmov ebx, 400\nmov ecx, 200\njmp 00401000\n<\/pre>\n<p>Wprowad\u017a powy\u017cszy program do OllyDbg. Aby wprowadzi\u0107 instrukcj\u0119, wystarczy klikn\u0105\u0107 na danej linijce dwukrotnie. Pojawi si\u0119 okienko assemble at, w kt\u00f3re wprowadzisz instrukcj\u0119 z przyk\u0142adu.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-152 size-full\" src=\"https:\/\/www.kompikownia.pl\/wp-content\/uploads\/2018\/03\/z3.png\" alt=\"Assemble at window\" width=\"325\" height=\"107\" \/><\/p>\n<p>Okno programu OllyDbg po wprowadzeniu instrukcji powinno wygl\u0105da\u0107 nast\u0119puj\u0105co:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-153 size-full\" src=\"https:\/\/www.kompikownia.pl\/wp-content\/uploads\/2018\/03\/z4-1.png\" alt=\"\" width=\"911\" height=\"672\" \/><\/p>\n<p>Obserwuj zawarto\u015b\u0107 rejestr\u00f3w i naciskaj F7. Na podstawie w\u0142asnej wiedzy oce\u0144, co robi ten program.<\/p>\n<p>Dobra. Skoro dalej czytasz, to powiem: <strong>robi<\/strong> bardzo wiele J Najpierw zapisuje w rejestrze EAX warto\u015b\u0107 100. Potem zapisuje do tego samego rejestru liczb\u0119 300. Nast\u0119pnie do ebx\u2019a kopiuje 400 a do ecx\u2019a 200. Na ko\u0144cu wykonywany jest skok do pierwszej linijki programu i ca\u0142a historia zaczyna si\u0119 od pocz\u0105tku \ud83d\ude42<\/p>\n<h1>Clue \u2013 mierzenie wydajno\u015bci<\/h1>\n<p>Zajmiemy si\u0119 teraz g\u0142\u00f3wnym celem naszych rozwa\u017ca\u0144 \u2013 mierzeniem wydajno\u015bci \ud83d\ude42<\/p>\n<pre lang=\"asm\">rdtsc\nmov ds:[00403000],eax\nmov ds:[00403004],edx\nmov eax,200\nmov eax,200\nmov eax,200\nmov eax,200\nrdtsc\nsub eax,ds:[00403000]\nsbb edx,ds:[00403004]\njmp 00401000\n<\/pre>\n<p>Co robi powy\u017cszy program? Ot\u00f3\u017c, ma on nam pokaza\u0107, jak wiele cykli procesora zajmuje zapisanie pewnej warto\u015bci w rejestrze procesora.<\/p>\n<p>Zajmijmy si\u0119 najpierw dok\u0142adn\u0105 analiz\u0105 pierwszej instrukcji: rdtsc. Wiesz ju\u017c mniej wi\u0119cej, co ona robi. Zapisuje do rejestr\u00f3w EAX i EDX liczb\u0119 cykli procesora, kt\u00f3re procesor prze\u017cy\u0142 od chwili uruchomienia. Lecz, jak wielkie s\u0105 to liczby? Przyjmijmy, \u017ce nasze CPU taktowane jest cz\u0119stotliwo\u015bci\u0105 3GHz. Oznacza to, \u017ce warto\u015b\u0107 ta przyrasta co chwil\u0119 o 3\u00a0000\u00a0000\u00a0000. Wydaje si\u0119, \u017ce jest to du\u017co \u2026 Obliczmy zatem \u00a0kiedy nasza 64 bitowa zmienna si\u0119 przepe\u0142ni.<\/p>\n<p>Para rejestr\u00f3w EAX, EDX pomie\u015bci maksymalnie 2^64. No ale procesor ma cz\u0119stotliwo\u015b\u0107 3*10^9 Hz, wi\u0119c nast\u0119puje niezgodno\u015b\u0107 pot\u0119g. Na potrzeby naszych oblicze\u0144 przyjmiemy pewne zaokr\u0105glenie.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-155 size-full\" src=\"https:\/\/www.kompikownia.pl\/wp-content\/uploads\/2018\/03\/z5.png\" alt=\"Obliczenia\" width=\"557\" height=\"162\" \/><\/p>\n<p>Dobra. Wiemy, \u017ce miejsca nam nie zabraknie. Analizujmy wi\u0119c kod dalej.<\/p>\n<p>Co robimy w nast\u0119pnych dw\u00f3ch linijkach? Pojawia si\u0119 tajemnicze ds., c\u00f3\u017c to takiego? ds oznacza data segment, czyli w skr\u00f3cie pami\u0119\u0107 RAM. To, co znajduje si\u0119 w nawiasach kwadratowych to adres w pami\u0119ci, pod kt\u00f3ry zostanie przeniesiona kolejno zawarto\u015b\u0107 rejestr\u00f3w EAX i EDX.<\/p>\n<p>Ale dlaczego zapisujemy to w pami\u0119ci RAM? Bo tego wymaga nasz algorytm post\u0119powania. Najpierw sprawdzamy, ile cykli procesor wykona\u0142 do tej pory. Zapisujemy t\u0119 informacj\u0119. Potem wykonujemy operacj\u0119, kt\u00f3rej wydajno\u015b\u0107 chcemy zmierzy\u0107, a nast\u0119pnie ponownie pobieramy ilo\u015b\u0107 cykli procesora wykonanych od startu PC-ta. Uzyskana r\u00f3\u017cnica b\u0119dzie poszukiwan\u0105 przez nas warto\u015bci\u0105.<\/p>\n<p>Mo\u017ce ci\u0119 zastanowi\u0107, dlaczego instrukcja mov eax, 200 powtarza si\u0119 a\u017c 4 razy \u2026 Odpowied\u017a jest prosta \u2013 dla zwi\u0119kszenia dok\u0142adno\u015bci. Zauwa\u017c, \u017ce po wykonaniu instrukcji RDTSC znajduje si\u0119 omawiane wcze\u015bniej przenoszenie zawarto\u015bci rejestr\u00f3w do pami\u0119ci RAM. Operacja ta, jak ka\u017cda, swoje cykle procesora kosztuje. I co najgorsze, te cykle wlicz\u0105 nam si\u0119 do ko\u0144cowego wyniku. Tak wi\u0119c, czym wi\u0119cej czasu poch\u0142onie nasza docelowa operacja, tym wi\u0119ksz\u0105 dok\u0142adno\u015b\u0107 uzyskamy.<\/p>\n<p>Je\u015bli dalej nie rozumiesz, wyobra\u017a sobie, \u017ce startujesz w biegu na 200 metr\u00f3w. Jeste\u015b sam sobie s\u0119dzi\u0105. Przed startem musisz zapisa\u0107 aktualny czas (godzin\u0119, minut\u0119, sekund\u0119). Potem przebiegasz 100 metr\u00f3w w t\u0119 i z powrotem. Ponownie troch\u0119 czasu zajmie ci najpierw spojrzenie na zegarek, a potem zapisanie odpowiedniej godziny. Oka\u017ce si\u0119, \u017ce wynik twojego pomiaru by\u0142 nader niedok\u0142adny. Ta niedok\u0142adno\u015b\u0107 stanie si\u0119 mniejsza, gdyby\u015b wyd\u0142u\u017cy\u0142 dystans biegu.<\/p>\n<p>Za\u0142\u00f3\u017cmy, \u017ce bieg zaj\u0105\u0142 ci 20 sekund, a zapisanie wyniku 2x5s. Wtedy \u0142\u0105czny wynik to 30s, a b\u0142\u0105d pomiarowy (10s) stanowi a\u017c 1\/3 ca\u0142ego wyniku. Ten sam b\u0142\u0105d pomiarowy nie wp\u0142ynie tak bardzo na wynik wtedy, kiedy b\u0119dziesz bieg\u0142 3600 sekund. Na zapisanie odpowiednich czas\u00f3w dalej b\u0119dziesz potrzebowa\u0142 tyle samo czasu (2x5s). Lecz tym razem pomy\u0142ka b\u0119dzie stanowi\u0142a tylko 1\/360 ca\u0142ego wyniku.<\/p>\n<p>Na koniec wyja\u015bnijmy tajemnic\u0119 dw\u00f3ch odejmowa\u0144. Dlaczego najpierw u\u017cywamy instrukcji sub, a nast\u0119pnie instrukcji sbb? Dla uproszczenia, przyjmijmy \u017ce komputer liczy w systemie dziesi\u0119tnym.<\/p>\n<p>Przypomnij sobie, jak wykonuje si\u0119 odejmowanie pisemne. Ile to jest 13-7? Odpowied\u017a wydaje si\u0119 prosta \u2013 6. I, co najwa\u017cniejsze, jest poprawna! Brawo.<\/p>\n<p>Ale, co musia\u0142e\u015b zrobi\u0107, aby wykona\u0107 te obliczenie? Po\u017cyczy\u0142e\u015b pewnie jedynk\u0119 z wcze\u015bniejszej pozycji. Dok\u0142adnie tak samo robi komputer.<\/p>\n<p>Jaki b\u0119dzie wynik dzia\u0142ania 6-9? Poprawna odpowied\u017a brzmi: 7! Dlaczego? Bo po\u017cyczyli\u015bmy \u201eniewidzialn\u0105\u201d jedynk\u0119 z poprzedniego miejsca.<\/p>\n<p>Sub wykonuje odejmowanie bez wzgl\u0119du na wszystko. Nie patrzy na to, czy wcze\u015bniej by\u0142o co\u015b po\u017cyczone czy nie. Jednak\u017ce, czasem mo\u017ce si\u0119 okaza\u0107, \u017ce odejmujemy mniejsz\u0105 liczb\u0119 od wi\u0119kszej. Wtedy we fladze CF zostanie zanotowana informacja o tym fakcie.<\/p>\n<p>I w\u0142a\u015bnie z tej flagi korzysta Sbb. Je\u015bli flaga CF jest r\u00f3wna 1, to \u201epo\u017cyczka\u201d wyst\u0105pi\u0142a wcze\u015bniej i nale\u017cy j\u0105 uzna\u0107 przy wynikach dzia\u0142a\u0144. Sp\u00f3jrz na poni\u017cszy przyk\u0142ad:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-157 size-full\" src=\"https:\/\/www.kompikownia.pl\/wp-content\/uploads\/2018\/03\/z6-1.png\" alt=\"Obliczenia Architektura System\u00f3w Komputerowych\" width=\"208\" height=\"65\" \/><\/p>\n<p>Obydwa wyniki s\u0105 poprawne! W drugim wypadku wyst\u0105pi\u0142a niewidzialna, dodatkowa \u201epo\u017cyczka\u201d kt\u00f3ra zapisana by\u0142a we fladze CF.<\/p>\n<p>No dobra, ale do czego nam to w\u0142a\u015bciwie potrzebne. Nie mogliby\u015bmy u\u017cy\u0107 po prostu sub? Nie, poniewa\u017c nasza liczba jest rozbita na dwie cz\u0119\u015bci. I odejmujemy dwie cz\u0119\u015bci oddzielnie. Tak samo, jak odejmuj\u0105c 24 od 16 musimy pami\u0119ta\u0107 w odpowiednich momentach o \u201epo\u017cyczce\u201d, tak samo i tutaj musimy pami\u0119ta\u0107, \u017ce przy odejmowaniu m\u0142odszych cz\u0119\u015bci liczb mo\u017ce wyst\u0105pi\u0107 konieczno\u015b\u0107 po\u017cyczki od starszej po\u0142owy tej liczby. I tak\u0105 po\u017cyczk\u0119 musimy uwzgl\u0119dni\u0107 w obliczeniach.<\/p>\n<p>No dobrze, a dlaczego zatem nie u\u017cyjemy dwa razy sbb? Jest prosty pow\u00f3d. Flaga CF mo\u017ce by\u0107 wcze\u015bniej zapalona (niekoniecznie przez nasz program) co mog\u0142oby zafa\u0142szowa\u0107 wyniki oblicze\u0144. Instrukcja sub wygasi flag\u0119 lub zapali j\u0105, kiedy b\u0119dzie potrzebna. Dzi\u0119ki temu sbb b\u0119dzie operowa\u0142a na w\u0142a\u015bciwym zestawie danych.<\/p>\n<p>Dobra. Skoro rozumiesz ju\u017c dzia\u0142anie powy\u017cszego programu to przepisz go do OllyDbg. Tym razem nasz tok post\u0119powania b\u0119dzie nieco inny. Po przepisaniu wszystkich instrukcji zaznacz ostatni\u0105 linijk\u0119 (t\u0119 ze skokiem &#8211; jmp). Nast\u0119pnie naci\u015bnij klawisz F2. Spowoduje to ustawienie pu\u0142apki (breakpointa). Pu\u0142apka b\u0119dzie zatrzymywa\u0142a program zawsze, gdy dojdzie do oznaczonego przez nas momentu. Nast\u0119pnie naci\u015bnij klawisz F8. Jaka liczba pojawi\u0142a si\u0119 w rejestrze EAX?<\/p>\n<h1>Podsumowuj\u0105c<\/h1>\n<p>Znasz ju\u017c kilka podstawowych poj\u0119\u0107 asemblera, wiesz z czym si\u0119 to je. Potrafisz tak\u017ce zmierzy\u0107 wydajno\u015b\u0107 wykonywania poszczeg\u00f3lnych instrukcji. Dla prze\u0107wiczenia spr\u00f3buj zmierzy\u0107, jak du\u017co cykli procesora zajmuje przeniesienie danych z rejestru do pami\u0119ci RAM.<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Czas czytania:<\/span> <span class=\"rt-time\">6<\/span> <span class=\"rt-label rt-postfix\">minut<\/span><\/span> Dzisiaj zajmiemy si\u0119 asemblerem w zakresie wymaganym na laboratoriach z &#8222;Architektura System\u00f3w Komputerowych&#8221;. Zanim zaczniemy, musimy pozna\u0107 kilka podstawowych poj\u0119\u0107. Musimy dowiedzie\u0107 si\u0119 mi\u0119dzy innymi, czym s\u0105 rejestry. Powinni\u015bmy tak\u017ce &#8230;<\/p>\n","protected":false},"author":1,"featured_media":463,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[23,24,22],"tags":[],"_links":{"self":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts\/143"}],"collection":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/comments?post=143"}],"version-history":[{"count":16,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts\/143\/revisions"}],"predecessor-version":[{"id":1159,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts\/143\/revisions\/1159"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/media\/463"}],"wp:attachment":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/media?parent=143"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/categories?post=143"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/tags?post=143"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}