---
# System prepended metadata

title: SyK Lista 4

---

# SyK Lista 4

## Zad. 1
[https://docs.oracle.com/cd/E19455-01/806-3773/instructionset-120/index.html](https://docs.oracle.com/cd/E19455-01/806-3773/instructionset-120/index.html)
setb - set byte if below (unsigned), CF
setl - set byte if less (signed), SF^OF
flagi:
* CF=1 if carry out from MSB (used for unsigned comparison)
* SF=1 if (b-a) < 0 (signed)
* OF=1 if two’s complement (signed) overflow
(b>0 && a<0 && (b-a)<0) || (b<0 && a>0 && (b-a)>0)

Gdy robimy cmp a b to tak naprawdę liczmy b-a

1) dla signed (setl):
    * a>=0 && b>=0
    Nie może wystąpić overflow, więc b-a jest takie, jak       powinno
        * a>b 
        b-a<0 więc SF=1, OF=0, SF^OF=1, setl ustawia 1, a           b jest mniejsze niż a, więc działa zgodnie z               oczekiwaniem
        * a\<=b
        b-a>=0 więc SF=0, OF=0, SF^OF=0, setl ustawia 0, a         b nie jest mniejsze niż a, więc działa zgodnie z           oczekiwaniem
    * a>=0 && b<0
    Jeśli wystąpi overflow (różnica będzie dodatnia,           chociaż nie powinna), wtedy SF=0, ale OF=1, więc           SF^OF=1, więc setl zadziała poprawnie  
    Jeśli overflow nie wystąpi, wtedy SF=1, ale OF=0, więc     setl nadal działa poprawnie
    * a<0 && b>=0
    Jeśli wystąpi overflow (różnica będzie ujemna,             chociaż nie powinna), wtedy SF=1, ale OF=1, więc           SF^OF=0, więc setl zadziała poprawnie  
    Jeśli overflow nie wystąpi, wtedy SF=0 oraz OF=0, więc     setl nadal działa poprawnie
    * a<0 && b<0
    Nie może wystąpić overflow, więc b-a jest takie, jak       powinno
        * a>b 
        b-a<0 więc SF=1, OF=0, SF^OF=1, setl ustawia 1, a           b jest mniejsze niż a, więc działa zgodnie z               oczekiwaniem
        * a\<=b
        b-a>=0 więc SF=0, OF=0, SF^OF=0, setl ustawia 0, a         b nie jest mniejsze niż a, więc działa zgodnie z           oczekiwaniem
2) dla unsigned (setb)
    * a<=b
    b-a wykona się poprawnie, nie zależnie od wielkości a       oraz b (nie może nastąpić pożyczenie z najbardziej         znaczącego bitu, ponieważ byłoby to zaprzeczeniem, że       a<=b), stąd CF=0, stąd setb zadziała zgodnie z             przewidywaniem
    * a>b
    W takim przypadku konieczne jest pożyczenie z bitu,         który jest już poza długością liczby, niezależnie ile       ta długośc wynosi (następuje carry), stąd zapali sie       CF, więc setb ustawi 1, się zadziała zgodnie z             oczekiwaniem
    
## Zad. 2
```
void who(short v[], size_t n)

who:
    subq $1, %rsi              // n = n - 1
    movl $0, %eax              // i = 0
.L2: cmpq %rsi, %rax           // |
    jnb .L4                    // while (i <= n)
    leaq (%rdi, %rax, 2), %rcx // |
    movzwl (%rcx), %r8d        // x = rdi[i]
    leaq (%rdi, %rsi, 2), %rdx // |
    movzwl (%rdx), %r9d        // y = rdi[n]
    movw %r9w, (%rcx)          // rdi[i] = y
    movw %r8w, (%rdx)          // rdi[n] = x
    addq $1, %rax              // i++
    subq $1, %rsi              // n--
    jmp .L2
.L4: ret
```
Zatem
```
void who(short v[], size_t n) {
    for (int i = 0, j = n - 1; i <= j; i++, j--) {
        short temp = v[i];
        v[i] = v[j];
        v[j] = temp;
    }
}
```
Czyli odwrócenie kolejności w tablicy.
Znajomość sygnatury nie jest istotna, gdyż widać że mamy do czynienia z tablicą, 
a instrukcje movW wskazują, że operujemy na shortach.


## Zad. 3

```
bool zonk(char * a, char* b)

zonk:
    movl $0, %ecx              // rcx = 0;
.L2: movslq %ecx, %rax         // long long rax = rcx;
    movzbl (%rdi, %rax), %edx  // rdx = rdi[rax];
    testb %dl, %dl             // |
    je .L6                     // if (dl == 0) { jump L6 }  
    cmpb %dl, (%rsi, %rax)     // 
    jne .L5                    // if (rdi[rax] != rsi[rax]) { jump L5 }
    addl $1, %ecx              // rcx++
    jmp .L2
.L6: orb (%rsi, %rax), %dl     // return (rdi[rax] | rsi[rax]) == 0
    sete %al
    ret
.L5: movl $0, %eax             // return false
    ret
```
Zatem 
```
bool zonk(char * a, char* b) {
    int i = 0;
    while (true) {
        char x = *(a + i);
        char y = *(b + i);
        if (x == '\0') {
            return x == y;
        }
        if (x != y) {
            return false;
        }
        ++i;
    }
}
```

Funkcja sprawdza, czy stringi (łańcuchy znaków) a i b są sobie równe.

## Zad 4

```
pusq src:
    subq $8, %rsp
    movq src, (%rsp)
    
popq dest:
    movq (%rsp), dest
    addq $8, %rsp
```

## Zad. 5
```
foo(int16_t v[], size_t n)

foo:    
    pushq   %rbp            // |
    movq    %rsp, %rbp      // |
    movq    %rdi, -24(%rbp) // |
    movq    %rsi, -32(%rbp) // |
    movq    $0, -8(%rbp)    // |
    jmp     .L2             // przygotowanie stosu: 0-7: i; 8-23: v[]; 24-31: n;
.L3:    
    movq    -8(%rbp), %rax      // rax = i
    leaq    (%rax,%rax), %rdx   // |
    movq    -24(%rbp), %rax     // |
    addq    %rdx, %rax          // |
    movzwl  (%rax), %eax        // rax = v[i]
    leal    (%rax,%rax), %edx   // rdx = 2*v[i]
    movq    -8(%rbp), %rax      // |
    leaq    (%rax,%rax), %rcx   // |
    movq    -24(%rbp), %rax     // |
    addq    %rcx, %rax          // |
    movw    %dx, (%rax)         // v[i] = rdx -> v[i] = 2*v[i]
    addq    $1, -8(%rbp)        // i++
.L2:    
    movq    -8(%rbp), %rax
    cmpq    -32(%rbp), %rax
    jb      .L3
    nop
    popq    %rbp
    ret
```
Zatem
```
void foo(int16_t v[], size_t n) {
    for (int i = 0; i < n; i++) {
        v[i] = 2*v[i];
    }
}
```
Funkcja mnoży każdy element tablicy przez 2
Stos:
|Dawny stos|
|---|
|rbp|
|i (początkowo 0)|
|?|
|rdi (*v[]) |
|rsi (n) |

## Zad. 6
```
reccur:
    pushq %rbp
    movq %rsp, %rbp
    subq $16, %rsp
    movl %edi, -4(%rbp)
    cmpl $0, -4(%rbp)  // |
    jne .L2            // if (x != 0) { jump L2 }
    movl $1, %eax      // |
    jmp .L3            // else return 1
.L2:
    movl -4(%rbp), %eax     // eax = x
    subl $1, %eax           // eax = x-1
    movl %eax, %edi         // |
    call reccur             // |
    imull -4(%rbp), %eax    // return eax*reccur(eax-1)
.L3:
    leave
    ret
```
Zatem
```
int reccur(int x) {
  if (x == 0) {
    return 1;
  }
  return x * reccur(x-1);
}
```
Silnia.

## Zad 7
Minimalna wartość n to 2, ponieważ
```
1 bar: pushq %rbp
2 movq %rsp, %rbp  | wrzucamy wskaźnik stosu do %rbp
3 .....
4 movl 16(%rbp), %eax  | wrzucamy do %raxa zawartość wskaźnika + 16 
5 popq %rbp
6 ret
```
Czyli stos musi wyglądać jakoś tak:
| Stos|
| -------- | 
| Rtn address | 
| %rbp(mówi gdzie jest wskaźnik %rsp) |
| być może coś tu jest ale chodziło o min n | 
| 16(%rbp) |
| 8(%rbp) |
| %rsp |

Zatem wywołanie bar powinno wyglądać tak:
```
pushl a2
pushl a1 
call bar
```
[https://zhu45.org/posts/2017/Jul/30/understanding-how-function-call-works/](https://)
Jak jest więcej argumentów niż się mieści w rejestrach od %rdi, %rsi, %rdx, %rcx, %r8, %r9 to się pozostałe wrzuca na stos
![](https://i.imgur.com/H6it6U8.png)

---



| co | rozmiar | |
| --- | --- | --- |
| ? | ? | 20(%rbp) |
| a7 | 4 | 16(%rbp) |
| Rtn adress | 8 | 8(%rbp) |
| %rbp | 8 | (%rbp) |

wtedy wywołanie bar(1,2,3,4,5,6,7): wygląda następująco:

```

movl $1, %edi
movl $2, %esi
movl $3, %edx
movl $4, %ecx
movl $5, %r8d
movl $6, %r9d
pusl %7
call bar
```