====== 1. Seznámení s učebnou, překladačem, simulátorem a základy reprezentace dat ====== * pro vyučující: [[..:..:internal:tutorials:01:start|cvičení 1]] ===== Osnova cvičení ===== - požadavky na zápočet, hodnocení - seznámení s učebnou - seznámení s terminálem - z C do assembleru - seznámení se simulátorem [[..:..:documentation:qtrvsim:start|QtRvSim]] - základní bitové operace s čísly (masky - bitový and, or; posuny operátory <<, >>) **Co bych si měl na první cvičení zopakovat / připravit?** - K přihlášení v KN:E-23 se používá **hlavní přístupové heslo ČVUT** ([[https://support.dce.felk.cvut.cz/mediawiki/index.php/Hesla_a_jejich_spr%C3%A1va_na_%C4%8CVUT/FEL|více o heslech]]) - základní terminálové příkazy ([[https://osy.pages.fel.cvut.cz/docs/cviceni/lab1/commands/ | základní UNIXové příkazy]]) - binární a hexadecimální reprezentace celých čísel - bitové operace s čísly (and, or, posuny, rotace, ...) - kapitolu 3 z {{ ..:..:lectures:apolos_v11.pdf|APOLOS}} - binární soustava a modulo aritmentika ===== Náplň cvičení ===== Cílem cvičení je seznámení s učebnou, zopakování základních pojmů na téma reprezentace dat v počítači a seznámení s návazností jazyků různé úrovně abstrakce až po strojový kód. Počítejte s tím, že se jedná pouze o přehled a získání představy čím se v našem předmětu budete zabývat. ==== Počítačová učebna ==== * [[courses:b35apo:documentation:classroom|Učebna KN-23]] * [[courses:b35apo:documentation:remote:start|Vzdálený přístup]] * V případě problémů s instalací kontaktuje Aleše Kapicu ze skupiny IT (http://support.dce.felk.cvut.cz/mediawiki/index.php/IT_kontakty) případně další kolegy ze skupiny IT, kteří mají správu hardware a sítí na starosti. **Terminálové příkazy** * [[https://osy.pages.fel.cvut.cz/docs/cviceni/lab1/commands/|Základní přehled terminálových příkazů (B4B35OSY)]]. * [[https://bootlin.com/doc/legacy/command-line/command_memento.pdf|Podrobnější jednostránkový přehled]] a [[https://bootlin.com/doc/legacy/command-line/unix_linux_introduction.pdf|prezentace]] ze stránek [[https://bootlin.com/|Bootlin]] ==== Domácí úkoly ==== * [[..:..:homeworks:start|domácí úkoly]] 1 až 4 budou zadané a odevzdávané elektronickou formou * vstup k zadání a odevzdání úkolů 1 a 3 je přes adresu [[https://dcenet.fel.cvut.cz/apo/|https://dcenet.fel.cvut.cz/apo/]] * Na stránce "Assignments" naleznete seznam zadaných úkolů * Pro vyzkoušení práce s odevzdávacím systémem je k dispozici nehodnocená varianta prvního úkolu **1st training homework** * Případnými problémy s odevzdávacím systémem se obracejte na svého cvičícího nebo u úkolů 1 a 3 přímo na autora/správce sytému [[courses:b35apo:teacher:susta:start|Richarda Šustu]] ==== Od programování na vyšší úrovni k strojovému kódu ==== === Programovací jazyk C === Jedná se o jazyk se striktně programátorem definovanými datovými typy. Vlastní vazba identifikátorů typů na způsob reprezentace se ovšem může lišit mezi architekturami, protože například typ pro celá čísla se znaménkem (''int'') reprezentuje takové kódování celých čísel alespoň v rozsahu −32,767 až +32,767, které nejlépe na zpracování vyhovuje danému cílovému procesoru. Na většině v dnešní době využívaných architektur je pak rozsah datového typu ''int'' −2,147,483,648 až +2,147,483,647 ($-2^{31}$ až $2^{31}-1$) a hodnota je ukládaná ve 32-bitech. Program je obvykle nutné před spuštěním zkompilovat (existují i jiné alternativy - [[https://root.cern.ch/cling|CERN ROOT Cling]]) do binární podoby, ve které může být načtený operačním systémem do paměti vlastní výpočet pak provádí přímo procesor podle přeložených/binárních strojových instrukcí. == hello-apo.c == Na příkladu C programu Hello world je možné předvést jak vypadá jeho kompilace pro různé architektury procesorů. Program uložíme pod jménem ''hello-apo.c''. #include int main(int argc, char *argv[]) { printf("Hello APO\n"); return 0; } Kompilace a spuštění pak vypadá následovně gcc -Wall -o hello-apo hello-apo.c ./hello-apo V adresáři ''/opt/apo/hello-apo'' na pracovních počítačích v laboratoři se nachází příklad včetně sestavovacího souboru ''Makefile'' pro různé architektury procesorů. Mimo počítače v laboratoři je možné k příkladům přistupovat přes webové rozhraní FEL instalace verzovacího systému GitLab nebo přímo přes jeho příklady (adresář [[https://gitlab.fel.cvut.cz/b35apo/stud-support/-/tree/master/seminaries/hello-apo|seminaries/hello-apo]] v repozitáři [[https://gitlab.fel.cvut.cz/b35apo/stud-support|https://gitlab.fel.cvut.cz/b35apo/stud-support/]]). Příklad stažení kompilace a spuštění na počítačích v laboratoři mkdir -p ~/apo cd ~/apo cp -r -L /opt/apo/hello-apo . cd hello-apo make ARCH=native make ARCH=native run Příklad je připravený tak, že na počítačích v laboratoři je možné za ARCH volit ''native'', ''x86'', ''riscv'', ''riscv64'', ''mips'', ''arm'' nebo ''aarch64''. == sum2vars.c == #include int var_a = 0x1234; int var_b = 0x2222; int var_c = 0x3333; int main() { var_c = var_a + var_b; printf("sum %d + %d -> %d\n", var_a, var_b, var_c); printf("sum 0x%x + 0x%x -> 0x%x\n", var_a, var_b, var_c); return 0; } Program zkompilujeme do binární podoby [[https://www.gnu.org/|GNU]] kompilátorem jazyka C ([[https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gcc/|manuál]]). gcc -Wall sum2vars.c Standardní jméno výstupního spustitelného souboru je ''a.out''. Program spustíme udáním názvu s cestou ''./a.out''. Požadované jméno binárního souboru můžeme specifikovat na příkazové řádce přepínačem ''-o'' stejně jako specifikovat vložení ladících informací ''-ggdb''. Kompilátor je dále možné požádat o optimalizaci programu na délku přepínačem ''-Os''. gcc -Wall -Os -ggdb -o sum2vars sum2vars.c Obsah binárního souboru ve formátu [[https://en.wikipedia.org/wiki/Executable_and_Linkable_Format|ELF]] je možné zkoumat například nástrojem [[https://sourceware.org/binutils/docs/binutils/objdump.html#objdump|objdump]]. objdump -S sum2vars Překlad na jednotlivé strojové instrukce je možné prozkoumat i online [[https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(fontScale:14,j:1,lang:c%2B%2B,selection:(endColumn:1,endLineNumber:18,positionColumn:1,positionLineNumber:18,selectionStartColumn:1,selectionStartLineNumber:18,startColumn:1,startLineNumber:18),source:'%23include+%3Cstdio.h%3E%0A%0Aint+var_a+%3D+0x1234%3B%0Aint+var_b+%3D+0x2222%3B%0A%0Aint+var_c+%3D+0x3333%3B%0A%0Aint+main()%0A%7B%0A++var_c+%3D+var_a+%2B+var_b%3B%0A%0A++printf(%22sum+%25d+%2B+%25d+-%3E+%25d%5Cn%22,+var_a,+var_b,+var_c)%3B%0A%0A++printf(%22sum+0x%25x+%2B+0x%25x+-%3E+0x%25x%5Cn%22,+var_a,+var_b,+var_c)%3B%0A%0A++return+0%3B%0A%7D%0A'),l:'5',n:'0',o:'C%2B%2B+source+%231',t:'0')),k:50,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:g92,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'1',trim:'1'),fontScale:14,j:1,lang:c%2B%2B,libs:!(),options:'-Os',selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1),l:'5',n:'0',o:'x86-64+gcc+9.2+(Editor+%231,+Compiler+%231)+C%2B%2B',t:'0')),k:50,l:'4',n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4|Godbolt Compiler Explorer]] === Assembler - jazyk symbolických adres === Zápis v jazyce C je přeložený na takovou posloupnost strojových instrukcí, která vykoná nad přesně specifikovanými datovými typy takové operace, že výsledek celého běhu programu, nebo běhu do sekvenčního bodu, je ekvivalentní zapsanému algoritmu. Výstup kompilátoru ve formátu již přesně daných instrukcí, ale bez rozhodnutí o jejich finálním umístění v paměťovém prostoru získáme pro nativní překlad (překlad pro systém, na kterém aktuálně kompilátor běží) příkazem gcc -Wall -Os -S -o sum2vars.s sum2vars.c Plné pochopení jak psát programy v assembleru pro architekturu x86_64 a pro běh pod operačním systémem GNU/Linux je náročné a proto jsme pro výuku procesorových architektur dříve volili architekturu MIPS ([[..:..:documentation:qtmips:start#volba_architektury_mips|důvody]]) a nyní přecházíme na otevřenější a modernější architekturu [[https://riscv.org/technical/specifications/|RISC-V]]. Na začátek budeme používat variantu v maximálně omezené a zjednodušené podobě. Aby bylo možné sledovat vnitřní stavy a princip činnosti procesoru, nebudeme používat přímo procesorové desky s [[..:..:documentation:embedded_systems/start#pic32mxpic32mx_levne_vykonnejsi_mikrokontrolery_na_bazi_architektury_mips|čipy]] implementujícími architekturu, ale grafický simulátor vytvořený přímo pro účely našeho kurzu - [[..:..:documentation:qtmips:start|QtMips]] ([[https://pretalx.linuxdays.cz/2019/talk/EAYAGG/|materiály]] a [[https://youtu.be/fhcdYtpFsyw|video]] z jeho představení na akci [[https://www.linuxdays.cz/2019/|LinuxDays 2019]]) nebo nyní novější [[https://github.com/cvut/qtrvsim|QtRvSim]]. Současný stav je výsledkem práce vašich předchůdců ([[https://dspace.cvut.cz/bitstream/handle/10467/94446/F3-BP-2021-Dupak-Jakub-thesis.pdf|bakalářská práce pana Dupáka]] a [[https://dspace.cvut.cz/bitstream/handle/10467/96707/F3-BP-2021-Hollmann-Max-thesis.pdf|bakalářská práce pana Hollmanna]]). Přitom následující ukázky jsou uvedené především pro získání přehledu, čím se budete během semestru zabývat. K zápisu algoritmu v instrukcích procesoru se vrátíme ve třetí přednášce a [[..:03:start|třetím cvičení]]. Pro první přiblížení zkompilujeme kód křížovým překladačem pro architekturu RISC-V riscv64-linux-gnu-gcc -ggdb -Os -Wall -static -fno-lto -o sum2vars-riscv sum2vars.c Program je možné v naší laboratoři pustit i na GNU/Linux systému s architekturou x86_64, protože binární soubory pro architektury MIPS, RISC-V, ARM a další jsou automaticky interpretované emulátorem [[https://www.qemu.org/|QEMU]] v režimu user-space emulace. Program také můžeme přeložit bez operačního systému, pokud z původního programu v C zakomentujeme výstupy: //#include int var_a = 0x1234; int var_b = 0x2222; int var_c = 0x3333; int main() { var_c = var_a + var_b; //printf("sum %d + %d -> %d\n", var_a, var_b, var_c); //printf("sum 0x%x + 0x%x -> 0x%x\n", var_a, var_b, var_c); return 0; } Překlad pak provedeme příkazem: riscv64-unknown-elf-gcc -march=rv32i -mabi=ilp32 -nostdlib -c sum2vars.c -o sum2vars.o Aby se program mohl spustit, je nutné ho inicializovat a spustit funkci main. K tomu můžeme využít soubor start.S: .globl _start .text .option norelax _start: la x2, _end+0x4000 la x3, __global_pointer$ jal main ebreak I modul start.S zkompilujeme a vytvoříme start.o riscv64-unknown-elf-gcc -march=rv32i -mabi=ilp32 -nostdlib -c start.S -o start.o Nyní z obou modulů sum2vars.o a start.o vytvoříme program: riscv64-unknown-elf-gcc -march=rv32i -mabi=ilp32 -nostdlib sum2vars.o start.o -o sum2vars-riscv -lgcc a můžeme ho nahrát do simulátoru {{ ..:qtmips-load-sum2vars.png?direct&400 |}} a odkrokovat. Manuální přepis do assembleru RISC-V (sobor ''sum2vars-riscv.S'') může vypadat následovně (pro zjednodušení bez volání funkce tisku) .globl _start .text _start: lw x4, var_a(x0) lw x5, var_b(x0) add x6, x4, x5 sw x6, var_c(x0) addi x2, x0, 0 jr ra .data .org 0x400 var_a: .word 0x1234 var_b: .word 0x2222 var_c: .word 0x3333 #pragma qtrvsim show registers #pragma qtrvsim show memory #pragma qtrvsim focus memory var_a #pragma qtrvsim tab core Tento program lze zkompilovat i přímo v simulátoru. Aby simulátor nenahrával externí program, spustíme ho v režimu bez nahrání ELF souboru. {{ ..:qtmips-start-empty.png?direct&400 |}} Zvolíme File -> New source Nyní se využijí i direktivy pro rychlé nastavení pozice ve výpisu paměti na proměnnou ''var_a'' a další. Zkompilujeme volbou Machine -> Compile source a můžeme ho odkrokovat. {{ ..:qtmips-with-legend.png?direct&400 |}} ===== Úkoly ===== - **S cvičícím si projděte výše uvedený přehled, čím se budete během semestru zabývat** * zkontrolujte si, že umíte na počítačích v laboratoři používat simulátor QtMips a QtRvSim * v případě, že vám není jasné, jak si simulátor nainstalovat doma, tak se zeptejte cvičících - **Studenti se pokusí upravit program pro součet dvou čísel tak** * aby vypisoval výsledek po jednotlivých bitech od bitu číslo ''31'' po bit ''0'' * aby bylo možné vstupní hodnoty specifikovat na příkazové řádce (argc, argv, atoi) * aby používal datové typy s menším rozsahem (short int, unsigned short int, unsigned char, signed char) * vyzkoušejte operace s kladnými i zápornými čísly, zaměřte se i na takové hodnoty, kdy po provedení operace dojde k přetečení - **Vyzkoušejte si ručně sčítání a odčítání celých čísel v doplňkovém kódu** * demonstrujte výpočet např. ''7+6, 7-6'' * procvičte výpočet na dalších číslech a s pomocí programu výsledky ověřte * Kdy může dojít k přetečení a jak poznáte, že k němu došlo? - **Násobení celých čísel** * demonstrujte výpočet např. ''7*6'' * jak se výpočet změní v případě záporných čísel? např. ''-7*6, -7*(-6), 7*(-6)'' * rychlá verze hw násobičky (jak zrychlit opakované sčítání na jedné sčítačce použitím většího množství sčítaček?) - **Dělení celých čísel** * demonstrujte výpočet např. ''42/7, 43/7'' * jak se výpočet změní v případě záporných čísel? **Co si zopakovat na druhé cvičení** - operace sčítání, odčítání, násobení a dělení - logické operace s binárními čísly (and, or, rotace, ...) - přečíst/zopakovat znalosti z {{ ..:..:lectures:apolos_v11.pdf|APOLOS}} - reprezentace reálných čísel ([[https://en.wikipedia.org/wiki/IEEE_754|IEEE 754]]) ===== Užitečné odkazy ===== * [[https://comparch.edu.cvut.cz/|Stránky s online verzí simulátoru QtRvSim a souvisejícími materiály]] * [[https://fosdem.org/2023/schedule/event/rv_qtrvsim/|představení rozhraní a použití simulátoru QtRvSim na konferenci FOSDEM panem Dupákem]] * [[https://support.dce.felk.cvut.cz/pos/cv1/|https://support.dce.felk.cvut.cz/pos/cv1/]] - Práce v příkazové řádce POSIXového systému, kompilace a její automatizace (make) * [[http://support.dce.felk.cvut.cz/pos/cv-langc/|http://support.dce.felk.cvut.cz/pos/cv-langc/]] - Základy jazyka C * [[http://www.gnu.org/software/libc/manual/html_node/Formatted-Output.html|http://www.gnu.org/software/libc/manual/html_node/Formatted-Output.html]] - Dokumentace k řízení formátovaného výstupu pro implementaci **printf** z knihovny funkcí pro jazyk C ([[http://www.gnu.org/software/libc/|GLIBC]]) z projektu [[http://www.gnu.org/|GNU]] * [[https://bootlin.com/doc/legacy/command-line/command_memento.pdf|Základní příkazy pro práci v příkazové řádce]] ([[https://bootlin.com/doc/legacy/command-line/unix_linux_introduction.pdf|prezentace]]) na [[https://bootlin.com/|Bootlin]]