# Lista 5 (1 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(2) | 4(2) | 5(2) |
| --------------------:| --- | --- | ---- | ----- | ----- |
| Andriy Bernad | X | X | | X | X | 6
| Wojciech Bogucki | X | X | X | X | ==X== | 8
| Michał Doros | X | X | X | X | X | 8
| Marko Golovko | X | X | | | | 2
| Magdalena Jarecka | X | X | X | ==X== | X | 8
| Szymon Jędras | | | | | | 0
| Heorhii Karpenko | | | | | | 0
| Szymon Kosakowski | X | X | X | X | | 6
| Izabella Kozioł | X | X | | | | 2
| Franciszek Malinka | X | X | X | X | X | 8
| Filip Pazera | X | X | X | X | X | 8
| Franciszek Pindel | X | X | X | X | X | 8
| Kacper Puchalski | X | X | X | X | | 6
| Kacper Solecki | X | X | X | X | X | 8
| Andrzej Tkaczyk | X | X | X | X | X | 8
| Łukasz Wasilewski | x | x | | | | 2
| Vladyslav Yablonskyi | X | X | | X | X | 6
| Adam Zyzik | X | X | X | X | X | 8
:::
## Zadanie 1
:::info
Autor: Izabella Kozioł
:::
Assembler:
```=
puzzle: testl %esi, %esi # n&n (flags: ZF, SF, PF, OF = 0, CF = 0, AF = undef)
je .L4 # ZF (equal/zero)
xorl %edx, %edx # i = 0 (flags : ZF, SF, PF; OF, CF = cleared, AF = undef)
xorl %eax, %eax # res = 0 (flags : ZF, SF, PF; OF, CF = cleared, AF = undef)
.L3: movl %edi, %ecx # tmp = x
andl $1, %ecx # tmp = 1 & tmp (flags ZF, SF, PF; OF, CF = cleared, AF = undef)
addl %ecx, %eax # res += tmp
sarq %rdi # x >> 1 (arythmetic) (flags : CF)
incl %edx # i += 1 (preserving the state of CF)
cmpl %edx, %esi # n : i (flags)
jne .L3 # ~ZF not equal/not zero
ret #
.L4: movl %esi, %eax # res = n
ret #
```
C:
```C=
int puzzle(long x, unsigned n){
// if (n == 0) return n;
int res = 0;
for(unsigned i = 0; i < n; i++){
int tmp = x & 1;
res += tmp;
x = x >> 1;
}
return res;
}
```
Działanie : Zliczanie zapalonych bitów w pierwszych n najmłodszych bitach liczby x.
## Zadanie 2
:::info
Autor: Adam Zyzik
:::
Funkcja `puzzle2(char* s, char* d)` zwraca długość najdłuższego prefiksu `s`, w którym każda litera występuje również w `d`.
```c99=
long puzzle2(char *s, char *d) {
char *pos_s = s;
while(true) {
char *pos_d = d;
bool found = false;
while(*pos_d) {
if (*pos_d == *pos_s) {
found = true;
break;
}
pos_d++;
}
if (!found) {
return pos_s - s;
}
pos_s++;
}
}
```
> [name=Andrzej Tkaczyk]
>:::spoiler
>```c=
> long puzzle2(char *s, char *d){
> for(char *a=s; ; a++){
> for(char *b=d; ; b++){
> if(*a == *b){
> break;
> }
> if(*b == 0){
> return a - s;
> }
> }
> }
>}
>```
>:::
```assembly=
puzzle2:
movq %rdi, %rax <<A>>
.L3: movb (%rax), %r9b <<B>>
leaq 1(%rax), %r8
movq %rsi, %rdx
.L2: movb (%rdx), %cl <<C>>
incq %rdx
testb %cl, %cl
je .L4
cmpb %cl, %r9b <<D>>
jne .L2
movq %r8, %rax <<E>>
jmp .L3
.L4: subq %rdi, %rax <<F>>
ret
```
```graphviz
digraph graphname {
START -> A
A -> B;
B -> C;
C -> D;
C -> F
D -> E
D -> C
E -> B
F -> KONIEC;
}
```
> [name=Franciszek Malinka] pierwszego while'a możesz na fora zamienić, drugiego zresztą też
:::spoiler
```c
long puzzle2_decoded(char *s /* rdi */, char *d /* rsi */) {
for (char *result = s ; ; result++) {
char first = *result;
for (char *crawl = d; *crawl != first; crawl++) {
if (*crawl == 0) {
return result - s;
}
}
}
}
```
:::
> [name=Franciszek Pindel] można jeszcze krócej (i nie robić `return` ani `break` w środku pętli)
:::spoiler
```c
/* s - %rdi
* d - %rsi */
long puzzle2(char *s, char *d) {
char *actD = d;
char *actS;
for (actS = s; *actD != '\0'; actS++)
for (actD = d; *actD != '\0' && *actD != *actS; actD++) ;
return actS - s - 1;
}
```
> [name=Franciszek Malinka] to Ci się skompiluje? `char *actS` jest lokalną zmienną w pętli, nie możesz tego użyć potem w returnie poza tą pętlą.
:::
> [name=Franciszek Pindel] teraz powinno być ok.
## Zadanie 3
:::danger
Autor: Szymon Kosakowski
:::
```assembly=
puzzle3:
movl %edi, %edi #B1
salq $32, %rsi
movl $32, %edx
movl $0x80000000, %ecx
xorl %eax, %eax
.L3: addq %rdi, %rdi #B2
movq %rdi, %r8
subq %rsi, %r8
js .L2
orl %ecx, %eax #B3
movq %r8, %rdi
.L2: shrl %ecx #B4
decl %edx
jne .L3
ret #B5
```
Graf przepływu sterowania
```graphviz
digraph g{
START->B1;
B1->B2;
B2->B3;
B2->B4;
B3->B4;
B4->B2;
B4->B5;
B5->END;
}
```
```c=
uint32_t puzzle3(uint32_t n, uint32_t d)
{
long new_d = ((long)d)<<32;
long new_n = n;
int count = 32;
uint32_t result_bit = 0x80000000;
uint32_t result = 0;
do{
new_n += new_n;
long tmp = new_n - new_d;
if(tmp >= 0){
result |= result_bit;
new_n = tmp;
}
result_bit >>= 1;
count--;
} while (count != 0)
return result;
}
```
Funkcja liczy $\lfloor\frac{n}{d}\rfloor$
przykład dla 4-bitowych n = 7, d = 2
#### 1
rsi:
| | | | | | | | |
|-|-|-|-|-|-|-|-|
|0|0|1|0|0|0|0|0|
rdi:
(od razu przesunięte w lewo)
| | | | | | | | |
|-|-|-|-|-|-|-|-|
|0|0|0|0|1|1|1|0|
eax:
| | | | |
|-|-|-|-|
|0|0|0|0|
|^| | | |
#### 2
rsi:
| | | | | | | | |
|-|-|-|-|-|-|-|-|
|0|0|1|0|0|0|0|0|
rdi:
| | | | | | | | |
|-|-|-|-|-|-|-|-|
|0|0|0|1|1|1|0|0|
eax:
| | | | |
|-|-|-|-|
|0|0|0|0|
| |^| | |
#### 3
rsi:
| | | | | | | | |
|-|-|-|-|-|-|-|-|
|0|0|1|0|0|0|0|0|
rdi:
| | | | | | | | |
|-|-|-|-|-|-|-|-|
|0|0|1|1|1|0|0|0|
(rsi - rdi > 0)
r8:
| | | | | | | | |
|-|-|-|-|-|-|-|-|
|0|0|0|1|1|0|0|0|
eax:
| | | | |
|-|-|-|-|
|0|0|1|0|
| | |^| |
#### 4
rsi:
| | | | | | | | |
|-|-|-|-|-|-|-|-|
|0|0|1|0|0|0|0|0|
rdi:
| | | | | | | | |
|-|-|-|-|-|-|-|-|
|0|0|1|1|0|0|0|0|
(rsi - rdi > 0)
r8:
| | | | | | | | |
|-|-|-|-|-|-|-|-|
|0|0|0|1|0|0|0|0|
eax:
| | | | |
|-|-|-|-|
|0|0|1|1|
| | | |^|
## Zadanie 4
:::danger
Autor: Magdalena Jarecka
:::
:::info
Poniżej zamieszczono kod rekurencyjnej procedury o sygnaturze «int puzzle4(long *a,long v, uint64_t s, uint64_t e)». Wyznacz bloki podstawowe oraz narysuj graf przepływu sterowania.Przetłumacz tę procedurę na język C, a następnie jednym zdaniem powiedz co ona robi
```c=
*a = rdi, v = rsi, s = rdx, e = rcx
r8 = mid
puzzle4:
movq %rcx, %rax // B1
subq %rdx, %rax
shrq %rax
addq %rdx, %rax
cmpq %rdx, %rcx
jb .L5
movq (%rdi,%rax,8), %r8 // B2
cmpq %rsi, %r8
je .L10
cmpq %rsi, %r8 // B3
jg .L11
leaq 1(%rax), %rdx // B4
call puzzle4
.L10: ret // B10
.L11: leaq -1(%rax), %rcx // B11
call puzzle4
ret
.L5: movl $-1, %eax // B5
ret
```
:::
```graphviz
digraph g{
L1 [label="B1"]
L2 [label="B2"]
L3 [label="B3"]
L4 [label="B4"]
L10 [label="B10"]
L11 [label="B11"]
L5 [label="B5"]
START
END
L1 -> L2
L2 -> L3
L3 -> L4
L1 -> L5
L2 -> L10
L3 -> L11
L4 -> L10
START -> L1
L5 -> END
L10 -> END
L11 -> END
}
```
#### Przeszukiwanie binarne
```c=
int puzzle4(long *a, long v, uint64_t s, uint64_t e)
{
uint64_t pos = s + (e - s) / 2;
if(e < s)
return -1;
long mid = a[pos];
if(mid == v)
return pos;
if(mid > v)
e = pos-1;
else
s = pos+1;
return
puzzle4(a, v, s, e);
}
```
## Zadanie 5
::: success
Autor: Wojciech Bogucki
:::
```scala=
400590 <switch_prob>: switch_prob:
400590: 48 83 subq $0x3c,%rsi
400594: 48 83 fe 05 cmpq $0x5,%rsi
400598: 77 29 ja *0x4005c3
40059a: ff 24 f5 f8 06 40 00 jmpq *0x4006f8(,%rsi,8)
4005a1: 48 8d 04 fd 00 00 00 00 .L0/1 lea 0x0(,%rdi,8),%rax
4005a9: c3 retq
4005aa: 48 89 f8 .L4 movq %rdi,%rax
4005ad: 48 c1 f8 03 sarq $0x3,%rax
4005b1: c3 retq
4005b2: 48 89 f8 .L2 movq %rdi,%rax
4005b5: 48 c1 e0 04 shlq $0x4,%rax
4005b9: 48 29 f8 subq %rdi,%rax
4005bc: 48 89 c7 movq %rax,%rdi
4005bf: 48 0f af ff .L5 imulq %rdi,%rdi
4005c3: 48 8d 47 4b .L3 leaq 0x4b(%rdi),%rax
4005c7: c3 retq
Zrzut pamięci przechowującej
tablicę skoków:
(gdb) x/6gx 0x4006f8
0x4006f8: 0x4005a1 :L0
0x400700: 0x4005a1 :L1
0x400708: 0x4005b2 :L2
0x400710: 0x4005c3 :L3
0x400718: 0x4005aa :L4
0x400720: 0x4005bf :L5
```
```c=
long switch_prob(long x, long n){
n-=0x3c;// stała 60, potrzebna gdy w switchu dajemy <0,5>
switch(n){
case 0:
case 1:
return x*8;
case 4:
return x/8;
case 2:
x = (x << 4) - x;
//x*=15;
case 5:
x*=x;
default:
return x + 0x4b;
}
}
```
> [name=Franciszek Malinka] w 10 linii w switch_prob nie powinieneś jeszcze odejmować x? Spójrz na wiersz 13 w assemblerze
> [name=Wojtek Bogucki] Faktycznie, poprawię.
> [name=Franciszek Malinka] powinno być raczej `x = (x << 4) - x`, powinna być jeszcze stara wartość `x`.
> [name=Wojtek Bogucki] Faktycznie, dzięki, poprawię.(Orginalnie było `x = x << 4;`, zostawaim dla potomnych.)