Zadanie nr 1
W ramach zadania domowego mieliśmy rozwinąć kod z pierwszych zajęć zamieniający litery małe na wielkie i odwrotnie. Nowy program dodaje do kodu ASCII każdej małej litery wartość 6 oraz do kodu każdej wielkiej litery wartość 8. Pozostałe znaki nie są zmieniane.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# deklaracja stałych .data STDIN = 0 STDOUT = 1 SYSREAD = 0 SYSWRITE = 1 SYSEXIT = 60 EXIT_SUCCESS = 0 BUFLEN = 512 POCZATEK_DUZYCH = 0x41 KONIEC_DUZYCH = 0x5A POCZATEK_MALYCH = 0x61 KONIEC_MALYCH = 0x7A # alokacja pamięci pod bufory na wczytywany # i wyświetlany tekst .bss .comm textin, 512 .comm textout, 512 .text .globl _start _start: # pobranie od użytkownika ciągu znaków mov $SYSREAD, %rax mov $STDIN, %rdi mov $textin, %rsi mov $BUFLEN, %rdx syscall # przeniesienie długości wczytanego ciągu do R8 # i wyzerowanie "licznika" RDI (potrzebnego dalej w pętli) mov %rax, %r8 mov $0, %rdi jmp petla petla: # odczyt znaku do rejestru AH mov textin(, %rdi, 1), %ah # jeśli kod znaku jest większy niż początek wielkich liter, # przeskok do etykiety duze cmp $POCZATEK_DUZYCH, %ah jge duze jmp powrot_do_petli duze: # jeśli kod znaku jest większy niż koniec wielkich liter, # przeskok do etykiety sprawdzaj_dalej cmp $KONIEC_DUZYCH, %ah jge sprawdzaj_dalej # w przeciwnym wypadku (znak to wielka litera) add $8, %ah # dodanie do kodu znaku liczby 8 jmp powrot_do_petli sprawdzaj_dalej: # jeśli kod znaku jest większy niż początek małych liter, # przeskok do etykiety male cmp $POCZATEK_MALYCH, %ah jge male jmp powrot_do_petli male: # jeśli kod znaku jest większy niż koniec małych liter, # przeskok do etykiety powrot_do_petli cmp $KONIEC_MALYCH, %ah jge powrot_do_petli # w przeciwnym przypadku (znak jest małą literą) add $6, %ah # dodanie do kodu znaku liczby 6 jmp powrot_do_petli powrot_do_petli: # zapis znaku do bufora wyjściowego movb %ah, textout(, %rdi, 1) # zwiększenie licznika i wykonanie kolejnych # iteracji pętli dla kolejnych znaków inc %rdi cmp %r8, %rdi jle petla # wyświetlenie danych zapisanych do bufora wyjściowego mov $SYSWRITE, %rax mov $STDOUT, %rdi mov $textout, %rsi mov %r8, %rdx syscall # zakończenie działania programu i zwrot wartości na wyjściu mov $SYSEXIT, %rax mov $EXIT_SUCCESS, %rdi syscall |
Zadanie nr 2
Przed zajęciami przygotować mieliśmy program konwertujący wprowadzone przez użytkownika liczby w systemie siódemkowym na system dziesiętny. Zadanie zostało rozszerzone na zajęciach o sprawdzanie czy użytkownik wprowadził prawidłowe znaki – cyfry systemu siódemkowego. W przypadku wprowadzenia innego znaku program wyświetla stosowny komunikat.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
.data # deklaracja stałych STDIN = 0 STDOUT = 1 SYSREAD = 0 SYSWRITE = 1 SYSEXIT = 60 EXIT_SUCCESS = 0 BUFLEN = 512 POCZATEK_LICZB = 0x30 # kod ASCII pierwszej liczby NOWA_LINIA = 0xA # kod ASCII znaku nowej lini PODSTAWA_WEJSCIA = 7 PODSTAWA_WYJSCIA = 10 komunikat: .ascii "W systemie 7-kowym nie ma takich znakow\n" komunikat_len = .-komunikat .bss # alokacja miejsc w pamięci .comm textin, 512 # bufor do którego zostanie # wczytany ciąg od użytkownika .comm textinv, 512 # bufor do którego zostanie # zapisany wynik w odwrotnej kolejności .comm textout, 512 # bufor wynikowy do którego przepisana # zostanie zawartość bufora textinv # w odwrotnej kolejności .text .globl _start # WCZYTANIE LICZBY OD UŻYTKOWNIKA _start: mov $SYSREAD, %rax mov $STDIN, %rdi mov $textin, %rsi mov $BUFLEN, %rdx syscall # ODCZYT Z KODU ASCII DO LICZBY W REJESTRZE mov %rax, %rdi # licznik do pętli (będzie liczył od końca) sub $2, %rdi # /n nas nie interesuje i liczymy od 0, a nie 1 mov $1, %rsi # kolejne potęgi 7 (na razie 1) mov $0, %r8 # miejsce na wynik globalny (na razie 0) jmp petla petla: # wyskok z pętli jeśli RDI jest mniejsze od 0 cmp $0, %rdi jl przed_petla2 mov $0, %rax # wyzerowanie RAX mov textin(, %rdi, 1), %al # odczyt litery do AL sub $POCZATEK_LICZB, %al # od teraz w AL jest liczba # jeśli po odjęciu od kodu znaku kodu początku liczb, # wartość będzie >= podstawie systemu wejściowego (7-kowego) # lub <=0, nastąpi przeskok do etykiety blad cmp $PODSTAWA_WEJSCIA, %al jge blad cmp $0, %al jl blad mul %rsi # pomnożenie RAX przez obecną potęgę 7-ki (RSI) add %rax, %r8 # dodanie obecnego wyniku (RAX/AL) # do globalnego (R8) # pomnożenie obecnej potęgi 7 (RSI) przez 7 ($PODSTAWA_WE) # mul wymaga umieszczenia mnożnej w rejestrze RAX # i nie pozwala na mnożenie przez zmienną ($PODSTAWA_WE -> RBX) mov %rsi, %rax mov $PODSTAWA_WEJSCIA, %rbx mul %rbx mov %rax, %rsi # zmniejszenie RDI i powrót na początek dec %rdi jmp petla # ZAPIS LICZBY Z REJESTRU DO KODU ASCII W BUFORZE przed_petla2: mov %r8, %rax # skopiowanie zdekodowanej liczby do rejestru RAX mov $PODSTAWA_WYJSCIA, %rbx mov $0, %rcx jmp petla2 petla2: mov $0, %rdx div %rbx # dzielenie bez znaku liczby z rejestru RAX przez RBX # i zapis wyniku do RAX oraz reszty z dzielenie do RDX. # reszta z dzielenia to przy każdej iteracji pętli kolejna # pozycja wyniku. po dodaniu kodu znaku pierwszej liczby, # są to kody znaków ASCII liczb na kolejnych pozycjach. add $POCZATEK_LICZB, %rdx # zapis znaków do bufora w odwrotnej kolejności mov %dl, textinv(, %rcx, 1) # zwiększenie licznika i w kolejnych iteracjach powrót # na początek pętli, aż do uzyskania zerowego wyniku dzielenia inc %rcx cmp $0, %rax jne petla2 jmp przed_petla3 # ODWRÓCENIE KOLEJNOŚCI # po wykonaniu ostatniego kroku, liczby zapisane są w buforze # w odwrotnej kolejności, w tej pętli są przepisywane z końca # na początek do nowego bufora textout. przed_petla3: mov $0, %rdi mov %rcx, %rsi dec %rsi jmp petla3 petla3: mov textinv(, %rsi, 1), %rax mov %rax, textout(, %rdi, 1) inc %rdi dec %rsi cmp %rcx, %rdi jle petla3 jmp wyswietl # WYŚWIETLENIE WYNIKU wyswietl: # dopisanie na końcu bufora wyjściowego znaku nowej linii movb $NOWA_LINIA, textout(, %rcx, 1) inc %rcx # wyświetlenie tekstu z bufora textout mov $SYSWRITE, %rax mov $STDOUT, %rdi mov $textout, %rsi mov %rcx, %rdx syscall # zwrot zera na wyjściu programu mov $SYSEXIT, %rax mov $EXIT_SUCCESS, %rdi syscall # WYŚWIETLENIE KOMUNIKATU BŁĘDU blad: mov $SYSWRITE, %rax mov $STDOUT, %rdi mov $komunikat, %rsi mov $komunikat_len, %rdx syscall # zwrot zera na wyjściu programu mov $SYSEXIT, %rax mov $EXIT_SUCCESS, %rdi syscall |
Zadanie nr 3
Na zajęciach przygotowaliśmy program kodujący i dekodujący ciągi liter podanych przez użytkownika przy użyciu szyfru cezara. Program przechowuje w pamięci ciąg cyfr dziesiętnych (zapisanych znakami ASCII) decydujących o liczbie przesunięć oraz znak +/- decydujący o tym czy będziemy szyfrować (+), czy deszyfrować (-). Liczba oraz znak zapisane są kodem ASCII. Kody ASCII zamieniane są na liczbę w rejestrze przy pomocy kodu z zadania domowego.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
.data STDIN = 0 STDOUT = 1 SYSREAD = 0 SYSWRITE = 1 SYSEXIT = 60 EXIT_SUCCESS = 0 BUFLEN = 512 KONIEC_LINI = 0xA MINUS = 0x2D POCZATEK_LICZB = 0x30 PODSTAWA_WEJSCIA = 10 ILOSC_LITER = 26 przesuniecie: .ascii "-55" przesuniecie_len = .-przesuniecie .bss .comm textin, 512 .comm textout, 512 .text .globl _start _start: # Pobranie ciągu do zakodowania od użytkownika mov $SYSREAD, %rax mov $STDIN, %rdi mov $textin, %rsi mov $BUFLEN, %rdx syscall # Przeniesienie długości wprowadzonego ciągu znaków do rejestru R9 mov %rax, %r9 dec %r9 # ODCZYT Z KODÓW ASCII DO LICZBY W REJESTRZ mov $przesuniecie_len, %rdi # licznik do pętli (będzie liczył od końca) sub $1, %rdi # liczymy od 0, a nie od 1 mov $1, %rsi # kolejne potęgi 10 (na razie 1) mov $0, %r8 # miejsce na wynik globalny (na razie 0) jmp petla petla: # wyskok z pętli jeśli RDI jest mniejsze od 1 cmp $1, %rdi jl przed_petla2 mov $0, %rax # wyzerowanie RAX mov przesuniecie(, %rdi, 1), %al # odczyt litery do AL sub $POCZATEK_LICZB, %al # od teraz w AL jest liczba mul %rsi # pomnożenie RAX przez obecną potęgę 10-ki (RSI) add %rax, %r8 # dodanie obecnego wyniku (RAX/AL) # do globalnego (R8) # pomnożenie obecnej potęgi 10 (RSI) przez 10 ($PODSTAWA_WE) # mul wymaga umieszczenia mnożnej w rejestrze RAX # i nie pozwala na mnożenie przez zmienną ($PODSTAWA_WE -> RBX) mov %rsi, %rax mov $PODSTAWA_WEJSCIA, %rbx mul %rbx mov %rax, %rsi # zmniejszenie RDI i powrót na początek dec %rdi jmp petla # WŁAŚCIWE SZYFROWANIE LUB DESZYFROWANIE # # szyfrowanie odbywa się zgodnie z wzorem: # (KOD_LITERY-'a'+PRZESUNIĘCIE) mod 26 + 'a' # deszyfrowanie: # (KOD_LITERY-'a'-PRZESUNIĘCIE) mod 26 + 'a' + 26* # * - jeśli wynik jest mniejszy niż 'a' # przed_petla2: mov $0, %rdi # licznik do pętli mov $ILOSC_LITER, %rcx # dzielnik jmp petla2 petla2: mov $0, %rax # wynik dzielenia (nieistotny) mov $0, %rdx # reszta z dzielenia mov textin(, %rdi, 1), %al # odczyt kolejnych znaków do AL sub $'a', %al # jeśli pierwszy znak zmiennej przesuniecie to minus: # skocz do dekoduj - odejmij przesunięcie mov $0, %r10 mov przesuniecie(, %r10, 1), %bl sub $MINUS, %bl jz dekoduj # w przeciwnym przypadku: koduj - dodaj przesunięcie add %r8, %rax jmp powrot_do_petli2 dekoduj: sub %r8, %rax jmp powrot_do_petli2 powrot_do_petli2: # jeśli kod znaku po przesunięciu jest ujemny, # przeskok do etykiety powrot_do_petli2_2 # i dopisanie ciągu FF..FF do uzupełnienia dzielnej, # tak aby podczas dzielenia, liczba była faktycznie # traktowana jako ujemna cmp $0, %rax jl uzupelnij_dzielna jmp powrot_do_petli2_2 uzupelnij_dzielna: mov $-1, %rdx # -1 w sys. dziesiętnym to w U16 ciąg FF..FF jmp powrot_do_petli2_2 powrot_do_petli2_2: idiv %rcx # dzielenie z uwzględnieniem znaku liczby # jeśli po dzieleniu, reszta z dzielenia jest ujemna, # przeskok do etykiety dodaj26, gdzie do reszty dodawana # jest ilość wszystkich liter w alfabecie (modulo 26) cmp $0, %rdx jl dodaj26 jmp powrot_do_petli2_3 dodaj26: add $26, %dl jmp powrot_do_petli2_3 powrot_do_petli2_3: # dodanie kodu pierwszej litery alfabetu, odjętego wcześniej # na potrzeby dzielenia modulo add $'a', %dl mov %dl, textout(, %rdi, 1) # zapisanie kodu litery do bufora wyjściowego # porót na początek pętli aż do wykonania operacji dla każdego znaku inc %rdi cmp %r9, %rdi jle petla2 # DOPISANIE NA KOŃCU BUFORA ZNAKU NOWEJ LINI mov $KONIEC_LINI, %al mov %al, textout(, %r9, 1) inc %r9 # WYŚWIETLENIE WYNIKU mov $SYSWRITE, %rax mov $STDOUT, %rdi mov $textout, %rsi mov %r9, %rdx syscall # ZWROT WARTOŚCI EXIT_SUCCESS mov $SYSEXIT, %rax mov $EXIT_SUCCESS, %rdi syscall |
Cześć :)
Czy będziesz wstawiać swoje rozwiązania do tematu z laboratorium 2: Utrwalenie umiejętności tworzenia prostych konstrukcji
programowych? Sporo pomagają one zrozumieć temat :D
Tak, zaraz to wrzucę
Nie wiedząc nic jestem w stanie się dużo nauczyć. Dzięki