---
# System prepended metadata

title: 'Lista 6 (15 kwietnia 2021), grupa KBa'
tags: [kba, ask21, ćwiczenia]

---

# Lista 6 (15 kwietnia 2021), grupa KBa

###### tags: `ask21` `ćwiczenia` `kba`

## Deklaracje

Gotowość rozwiązania zadania należy wyrazić poprzez postawienie X w odpowiedniej kolumnie! Jeśli pożądasz zreferować dane zadanie (co najwyżej jedno!) w trakcie dyskusji oznacz je znakiem ==X== na żółtym tle.

**UWAGA: Tabelkę wolno edytować tylko wtedy, gdy jest na zielonym tle!**

:::danger
|                      | 1   | 2   | 3   | 4   | 5   | 6   | 7   | 8(B) |
| --------------------:| --- | --- | --- | --- | --- | --- | --- | ---- |
|        Andriy Bernad |  X  |  X  |  X  |  X  |     |  X  |     |      | 5
|     Wojciech Bogucki |  X  |  X  |     |  X  |     |  X  |     |      | 4
|         Michał Doros |  X  |  X  |     |  X  |  X  |  X  |  X  |      | 6
|        Marko Golovko |  X  |  X  |     |     |     |     |     |      | 2
|    Magdalena Jarecka |     |     |     |     |     |     |     |      | 0 
|        Szymon Jędras |  X  |==X==|     |  X  |  X  |  X  |     |      | 5
|     Heorhii Karpenko |  X  |  X  |  X  |  X  |     |  X  |     |      | 5
|    Szymon Kosakowski |  X  |  X  |  X  |     |  X  |  X  |     |      | 5
|      Izabella Kozioł |     |     |     |     |     |     |     |      | 0
|   Franciszek Malinka |  X  |  X  |     |  X  |     |  X  |  X  |      | 5
|         Filip Pazera |  X  |  X  |     |  X  |     |  X  |     |      | 4
|    Franciszek Pindel |  X  |  X  |  X  |  X  |     |  X  |  X  |      | 6
|     Kacper Puchalski |  X  |  X  |  X  |     |     |  X  |     |      | 4
|       Kacper Solecki |  X  |  X  |     |  X  |     |  X  |  X  |      | 5
|      Andrzej Tkaczyk |  X  |  X  |     |  X  |     |  X  |  X  |      | 5
|    Łukasz Wasilewski |     |  x  |  x  |  x  |  x  |  x  |     |      | 5
| Vladyslav Yablonskyi |  X  |  X  |  X  |     |     |  X  |     |      | 4
|           Adam Zyzik |  X  |     |     |  X  |     |  X  |     |      | 3
:::

## Zadanie 1

:::info
Autor: Adam Zyzik
:::

![](https://i.imgur.com/yt96GuO.png)

```c=
long puzzle(long n, long *p) {
    long result = 0;
    if(n > 0) {
        long temp;
        puzzle(2 * n, &temp);
        result += temp;
        n += result;
    }
    *p  = n;
    return result;
}
```

Rekord aktywacji:
* adres powrotu (chyba że zaliczamy go poprzedniej ramki)
* poprzednia wartość **%rbp**
* poprzednia wartośc **%rbx**
* puste 8 bajtów
* zmienna lokalna **temp**
* puste 8 bajtów

Calee-saved registers: **%rbx**, **%rbp**

Zmienne lokalne: **temp**

## Zadanie 2

:::info
Autor: Szymon Jędras
:::
![](https://i.imgur.com/GkmwRdv.png)

```=c

struct T{
    long max;
    long min;
    long average;
};

struct T puzzle8(long* a, long n){
	// wskaznik na ret jest przekazany funkcji w rdi
	// wiec argumenty zaczynają sie od rsi zatem:
	// rsi = a, rdx = n
	struct T result;
	long sum = 0;
	long max = LONG_MIN;
	long min = LONG_MAX;
	// i jest przechowywane w r10
	for(int i = 0; i < n; i++) {
		if(min < a[i]) min = a[i];
		if(max > a[i]) max = a[i];
		sum += a[i];
	}
	// po wyjściu z pętli rax jest konwertowany do octoword 
	//	zeby mozna było użyć idiv
	sum /= n;
	result.min = min;
	result.max = max;
	result.average = sum;
	return result;
}
```
Gdyby sygnatura procedury nie była wcześniej znana to powiedziałbym że jest to:
`struct T* puzzle8(struct T* ret, long* a, long n)`


## Zadanie 3

:::success
Autor: Andriy Bernad
:::

:::info
Zadanie 3. Zakładamy, że producent procesora nie dostarczył instrukcji skoku pośredniego. Rozważmy procedurę  «switch_prob»  z  poprzedniej  listy.  Podaj  metodę  zastąpienia  «jmpq *0x4006f8(,%rsi,8)» ciągiem innych instrukcji. Nie można używać kodu samo modyfikującego się(ang.self-modyfing code),ale można użyć dodatkowego rejestru. Zastanów się czy potrafisz również zastąpić instrukcję pośredniego wywołania procedury, np. «call *(%rdi,%rsi,8)», gdyby jej brakowało.
:::

Tryby adresowania : 
**bezpośredni** - podajemy 32 bitową stałą, która określa przesunięcie względem początku pamięci (czyli adresu 0)
**pośredni** przez rejestr - adres znajduje się w jednym z 32/64 bitowych rejestrów.



![](https://i.imgur.com/2BOhKie.png)

Wykorzystamy rejestr `%r8` jako pomocniczy.

push wrzuci ten adres na stos.

ret go zdejmie i włoży do `%rip`, rip wskazuje aktualnie wykonywane polecenie.


```asm=
        movq  0x4006f8(,%rsi,8), %r8
        push %r8
        ret
```


Niepoprawne rozwiązanie p. Kacpra Puchalskiego:

:::spoiler
Możemy użyć rejestru %rip. To rejestr wskazujący na adres następnej wykonywanej przez nas instrukcji. 
Wystarczy więc podmienić skok na załadowanie adresu instrukcji do %rip
jpmq  $*0x4006f8(,\%rsi,8) \rightarrow$ leaq  $0x4006f8(,\%rsi,8), \%rip$
:::

## Zadanie 4

:::success
Autor: Filip Pazera
:::

```diff=
M: 
    pushq %rdi
    testq %rdi, %rdi
    je .L2
    leaq -1(%rdi), %rdi
    call M
    movq %rax, %rdi
    call F
-   movq (%rsp), %rdi   ; nie aktualizujemy %rsp
+   popq %rdi
    subq %rax, %rdi
.L2: 
    movq %rdi, %rax
    ret
    

    
F: 
    testq %rdi, %rdi
    je .L3
+   pushq %r12
    movq %rdi, %r12     ; %r12 jest callee-saved
    leaq -1(%rdi), %rdi
    call F
    movq %rax, %rdi
    call M
    subq %rax, %r12
    movq %r12, %rax
+   popq %r12
    ret
.L3: 
    movl $1, %eax
    ret
```

:::spoiler Poprawiona procedura M
```diff=
M:  pushq   %rdi
    testq   %rdi, %rdi
    je      .L2
    leaq    -1(%rdi), %rdi
    call    M
    movq    %rax, %rdi
    call    F
    movq    (%rsp), %rdi
    subq    %rax, %rdi
.L2: 
+   addq    $8, %rsp
    movq    %rdi, %rax
    ret
```
:::
## Zadanie 5

:::info
Autor: Michał Doros
:::
leave <=>
movq %rbp %rsp
popq %rbp
przechodzimy do poprzedniej ramki stosu

alloca alokuje n bajtów miejsca na stosie i zwalnia je automatycznie przy wyjściu z procedury, która ją wywołała

```c=
```c=
       0: 55                                pushq %rbp
       1: 48 89 e5                          movq %rsp, %rbp
       4: 48 83 ec 10                       subq $16, %rsp         
       8: 48 89 e0                          movq %rsp, %rax        #wsk stosu to rax
       b: 48 8d 0c fd 0f 00 00 00           leaq 15(,%rdi,8), %rcx #n * rozmiar longa + 15 do rcx (+15 to kwestia wyrównania/sufit)
      13: 48 83 e1 f0                       andq $-16, %rcx        #zerujemy ostatnie 4 bity
      17: 48 29 c8                          subq %rcx, %rax        #oblicz nowy wskaźnik stosu
      1a: 48 89 c4                          movq %rax, %rsp        #nowy wskaźnik wrzuć do rsp
      1d: 48 8d 4d f8                       leaq -8(%rbp), %rcx
      21: 48 89 4c f8 f8                    movq %rcx, -8(%rax,%rdi,8)
      26: 48 c7 45 f8 00 00 00 00           movq $0, -8(%rbp)
      2e: 48 85 ff                          testq %rdi, %rdi
      31: 7e 1d                             jle 29 <_aframe+0x50>
      33: 31 c9                             xorl %ecx, %ecx
      35: 66 2e 0f 1f 84 00 00 00 00 00     nopw %cs:(%rax,%rax)
      3f: 90                                nop
      40: 48 89 14 c8                       movq %rdx, (%rax,%rcx,8)
      44: 48 ff c1                          incq %rcx
      47: 48 39 cf                          cmpq %rcx, %rdi
      4a: 75 f4                             jne -12 <_aframe+0x40>
      4c: 48 89 7d f8                       movq %rdi, -8(%rbp)
      50: 48 8b 04 f0                       movq (%rax,%rsi,8), %rax
      54: 48 8b 00                          movq (%rax), %rax
      57: 48 89 ec                          movq %rbp, %rsp          #powrót do poprzedniej ramki
      5a: 5d                                popq %rbp                #wrzucenie do rbp poprzedniego adresu
      5b: c3                                retq

```

## Zadanie 6

:::info
Autor: Andrzej Tkaczyk
:::
```=
puzzle5:
    subq $24, %rsp
    movq %rsp, %rdi
    call readlong
    leaq 8(%rsp), %rdi
    call readlong
    movq (%rsp), %rax
    cqto
    idivq 8(%rsp)
    xorl %eax, %eax
    testq %rdx, %rdx
    sete %al
    addq $24, %rsp
    ret
```
```c=
void readlong(long *target);
```
```c=
long puzzle5(void){
  long a, b;
  readlong(&a);
  readlong(&b);
  return a % b == 0;
}
```
rekord aktywacji:
| zawartość | wielkość|
|-----------|---------|
| puste     | 8 bajtów|
| miejsce na wpisanie dla readlong | 8 bajtów|
| miejsce na wpisanie dla readlong | 8 bajtów|
| adres powrotu przy wołaniu readlong| 8 bajtów|

## Zadanie 7

:::success
Autor: Kacper Solecki
:::

```c=
typedef struct {
   // odstęp od reg_save_area do miejsca gdzie trzymany jest
   // następny argument (przekzany przez rejestr)
   unsigned int gp_offset;
   // podobny odstęp dla liczb zmiennoprzecinkowych - nie będzie nas interesować
   unsigned int fp_offset;
   // pokazuje na miejsce na stosie gdzie zachowane będą argumenty nadmiarowe (7+)
   void *overflow_arg_area;
   // pokazuje na miejsce na stosie gdzie zachowane będą argumenty z rejestrów
   void *reg_save_area;
} va_list[1];
```

Stos:
![](https://i.imgur.com/EAvV0Uj.jpg =400x)


Funkcja przyjmuje liczbę argumentów $n$ i sumuje $n$ kolejnych argumentów.
```c=
long puzzle7(long n, ...){
    struct va_list va;
    va_start(va, n);
    long sum = 0;
    for(int i=0; i<n; i++){
        sum += va_arg(va, long);
    }
    va_end(va);
    return sum;
}
```

## Zadanie 8

:::danger
Autor: Maksymilian Debeściak
:::