Cvičenia z predmetu Programovanie na strojovej úrovni (ISU), druhý semester bakalárskeho štúdia BIT na FIT VUT/BUT, ak.rok 2021/2022
Toto je archív mojích kódikov z ISU cvičení, ktoré som znovu–objavil na starom VPS (aspoň čo sa zachovalo), plus samouka na testy. Všetky súbory sú závislé na podpornej knižnici rw32-2022.inc (MOODLE.vut.cz, archive.org).
Ak sa Vám nechce nič nastavovať, vždy je tu SASM.
Windows prevažne bude mať nainštalované knižnice čo potrebujete. Stiahnite si archív z ISU MOODLE isu-tools-2022.zip (resp. verziu s aktuálnym rokom), kde by ste mali mať súbory bin/nasm.exe a bin/golink.exe (prípadne isu-vscode-mingw.zip). Cez shell potom môžete spustiť napr. test.asm takto:
bin/nasm.exe -f win32 -g -o build/test.obj test.asm
bin/golink.exe build/test.obj /fo build/test.exe /console /debug coff /entry:_main msvcrt.dll kernel32.dll
build/test.exeWindows som osobne nepoužíval, tak VSCode súbory nemám po ruke, ale menším refactoringom by sa z priložených linuxáckych dali spraviť. Something something, use Linux.
Na programovanie v x86 Assembly je potrebné mať nainštalovaný asembler NASM spolu s C-čkovými utilitkami a GNU toolchain — GCC, GDB + C knižnice — čo sa všetko dá nainštalovať ako package group. K tomu je treba doinštalovať 32–bitové knižnice.
nasm -f elf32 -g -o build/test.o test.asm
gcc -m32 -o build/test build/test.o
build/testapt -y update
apt -y install binutils build-essential gdb # Development tools
apt -y install gcc-multilib # 32-bit libraries
apt -y install nasmdnf -y upgrade
dnf -y group install "C Development Tools and Libraries"
dnf -y install glibc-devel.i686 # 32-bit libraries
dnf -y install nasmpacman -Syu
pacman -S base-devel # Development tools, install all
pacman -S lib32-gcc-libs # 32-bit libraries
pacman -S nasmProces spúšťania si môžete automatizovať súbormi launch.json a tasks.json v priečinku .vscode, čo spolu s rozšírením GDB Debug[REPO] Vám dá možnosti kód debuggovať.
Pre debugging použite klávesu F5, alebo spustite súbor klávesami CTRL + F5 bez debugu. Na debugging treba do kódu pridať breakpointy (tie červené bodky), kde program sa pozastaví, a môžete v ňom krokovať (pomocou tlačidiel v hornom menu) a pri tom sledovať registre, premenné, a podobne. Pokiaľ Vám nejde pridávať breakpointy, treba ich povoliť vo VSCode nastaveniach (File > Preferences > Settings > Debug: Allow Breakpoints Everywhere).
- x86 and x86_64 Assembly[REPO] — syntax highlighting
- ISU ASM Register Extension[REPO] — lepšie zobrazenie registrov počas debuggingu
- x86 Instruction Reference[REPO] — offline dokumentácia x86 inštrukcií
Všetky tieto rozšírenia sú povolené na cvičeniach aj na testoch (pozor: počas môjho štúdia, pravidlá sa mohli zmeniť!).
Na ľavej strane rozhrania v tabe Run & Debug máte panel Watch, pomocou ktorého môžete zobrazovať aktuálne hodnoty registrov či premenných (= miest v pamäti).
$REG: Zobrazí hodnotu registra REG VAR: Zobrazí hodnotu premennej VAR &VAR: Zobrazí adresu premennej VAR *ADDR: Zobrazí hodnotu miesta v pamäti ADDR *ADDR-ADDR: Zobrazí hodnoty miest v pamäti v rozsahu ADDR-ADDR
Takže napríklad hodnotu EAX zobrazíte výrazom $eax, alebo BL výrazom $bl.
Pretože assembly neuchováva typ "premenných" (a po kompilácií ani veľkosť), je nutné použiť cast na pretypovanie.
char— znakint— celé číslostring— reťazec znakovfloat— číslo s pohyblivou rádovou čiarkou
char je nositeľ typu aj veľkosti (8–bit), no int typu je veľkosť automaticky určená, čo nemusí byť vždy správne (hlavne pri poliach).
char— 8–bitov (DB)short— 16–bitov (DW)long— 32–bitov (DD)long long— 64–bitov (DQ)
Veľkosti a typy môžu byť osobitne, napr. (int)(short)varname, alebo kombinovane, napr. (short int)varname - k tomu ešte je možné špecifikovať znamienkovosť, napr. (unsigned short int)varname (vyberte si, čo Vám vyhovuje najviac — jedine pri 8-bit int treba presne použiť (int)(char)varname).
A ako posledné máte niekoľko možností formátu výpisu (píše sa za výrazom, oddelené čiarkou):
d— celé číslo so znamienkomu— celé číslo bez znamienkax— celé číslo v hexadecimálnej (šesnáctkovej) sústavet— celé číslo v binárnej (dvojkovej) sústave (t ako two)o— celé číslo v oktálovej (trojkovej) sústavec— znakf— číslo s pohyblivou rádovou čiarkou
Tu máte zopár možností na výpis (aj s poliami). Vyberte si, čo Vám príde najintuitívnejšie:
Tabuľka výpisových výrazov
| Type of value | Watch expression methods |
|---|---|
| String (any sized ptr) | &varname,s |
| Integer at the top of the stack | *(int)$esp |
| 8-bit (DB) signed int | (char)varname,d(signed char)varname,d(int)(char)varname(signed int)(char)varname |
| 8-bit (DB) unsigned int | (unsigned int)(char)varname(int)(unsigned char)varname |
| 8-bit (DB) int in hex | (char)varname,x(int)(char)varname,x |
| 8-bit (DB) char | (char)var(char)var,c |
| 16-bit (DB) signed int | (short int)varname(short signed int)varname(short)varname,d |
| 16-bit (DW) unsigned int | (short unsigned int)varname |
| 16-bit (DW) int in hex | (short int)var,x(short)var,x |
| 32-bit (DD) signed int | (long int)var(long signed int)var(long)int,d |
| 32-bit (DD) unsigned int | (long unsigned int)varname |
| 32-bit (DD) int in hex | (long int)varname,x(long)varname,x |
| 32-bit (DD) float | (float)varname |
| 64-bit (DQ) signed int | (long long int)varname(long long signed int)varname(long long)varname,d |
| 64-bit (DQ) unsigned int | (long long unsigned int)varname |
| 64-bit (DQ) int in hex | (long long int)varname,x(long long)varname,x |
| 64-bit (DQ) float | (double)varname |
| 10-elm array of 8-bit signed ints | (char[10])varname,d |
| 10-elm array of 8-bit unsigned ints | (iba ako unsigned char)(unsigned char[10])varname |
| 10-elm array of 8-bit ints in hex | (char[10])varname,x |
| 10-elm array of 16-bit signed ints | (short int[10])varname(short[10])varname,d(signed short[10])varname,d |
| 10-elm array of 16-bit unsigned ints | (unsigned short int[10])varname |
| 10-elm array of 16-bit ints in hex | (short[10])varname,x(short int[10])varname,x(signed short[10])varname,x |
Debug console je priamy prístup do debuggeru gcc, čo je fajn pomôcka, aj keď menej user-friendly. V tejto konzole môžete písať rovnaké výrazy ako do Watch panelu, alebo vykonávať príkazy pomocou -exec.
-exec info reg: Zobrazí hodnoty registrov -exec info float: Zobrazí všetko možné o FPU -exec info br: Zobrazí zoznam breakpointov -exec info stack: Zobrazí call stack -exec c: Pokračovať v programe -exec kill: Ukončí program -exec q: Ukončí GDB -exec n: Prejde na ďalšiu inštrukciu (vnorí sa do funkcie) -exec ni: Prejde na ďalšiu inštrukciu (bez vnorenia) -exec p $eax: Vypíše hodnotu registra EAX -exec disassemble: Zobrazí raw asm kód aktuálneho kontextu
Čo z toho je užitočné je už vec názoru, je to skôr niečo pre terminal master race hackermanov, inak za zaobídete aj bez tohoto. Asi jediný príkaz, čo som osobne používal, je -exec info float.
Dávam sem aj moje 💩 snippety v súbore isu.code-snippets. Je to len čiastočný copy-paste z prezentácií, ktorý som druhú polovicu semestra skoro vôbec neaktualizoval — skôr to prikladám ako šablónu, keby ste sa s tým chceli pohrať a spraviť si vlastné. U nás boli vlastné snippety povolené aj na písomkách (pozor: nemusí platiť aj tento rok!).



