###### tags: `ASK`
# Lista 4
## Zadanie 1

Oblicz wartość poniższych operandów źródłowych operacji *movq*:
1. `%rax` $\to$ `0x100`
2. `0x110` $\to$ `0x13`
3. `$0x108` $\to$ `0x108` (`$` - używany do oznaczenia stałych)
4. `(%rax)` $\to$ `0xFF`
5. `8(%rax)` $\to$ `(%rax + 8)` $\to$ `(0x108)` $\to$ `0xAB`
6. `21(%rax,%rdx)` $\to$ `(%rax + %rdx + 21)` $\to$ `(0x100 + 3 + 21)` $\to$ `(0x118)` $\to$ `0x11`
7. `0xFC(,%rcx,4)` $\to$ `(4 * %rcx + 0xFC)` $\to$ `(0x4 + 0xFC)` $\to$ `(0x100)` $\to$ `0xFF`
8. `(%rax,%rdx,8)` $\to$ `(0x100 + 8 * %rdx)` $\to$ `(0x100 + 24)` $\to$ `(0x118)` $\to$ `0x11`
9. `265(%rcx,%rdx,2)` $\to$ `(%rcx + 2 * %rdx + 265)` $\to$ `(1 + 6 + 265)` $\to$ `(272)` $\to$ `(0x110)` $\to$ `0x13`
## Zadanie 2
| instrukcja | adres / rejestr | wartość |
| ------------------------ | --------------------- | --------------------------------------------------|
| `addq %rcx,(%rax)` | `0x100` | `0xFF + 0x1 = 0x100` |
| `subq 16(%rax),%rdx` | `%rdx` |`3 - (0x100 + 16) = 3 - (0x110) = 3 - 0x13 = -0x10`|
| `shrq $4,%rax` | `%rax` | `0x100 >> 4 = 0x10` |
| `incq 16(%rax)` |`(%rax + 16) = (0x110)`| `0x13 + 0x1 = 0x14` |
| `decq %rcx` | `%rcx` | `0x1 - 0x1 = 0x0` |
| `imulq 8(%rax)` | `%rax` | `(%rax + 8) * %rax = 0xAB * 0x100= 0xAB00` |
|`leaq 7(%rcx,%rcx,8),%rdx`| `%rdx` | `(%rcx + 8 * %rcx + 7) = (0x10) => 0x10` |
| `leaq 0xA(,%rdx,4),%rdx` | `%rdx` |`(%rdx * 4 + 0xA) = (0xC + 0xA) = (0x16) => 0x16` |
`imul` one-operand form — This form is identical to that used by the MUL instruction. Here, the source operand (in a general-purpose register or memory location) is multiplied by the value in the AL, AX, EAX, or RAX register (depending on the operand size) and the product (twice the size of the input operand) is stored in the AX, DX:AX, EDX:EAX, or RDX:RAX registers, respectively.
## Zadanie 3 - brak
$s_0 = x_0$
$s_i = \alpha \cdot x_i + (1 - \alpha) \cdot s_{i-1},\ \ \ i > 0$
## Zadanie 4
W wyniku deasemblacji procedury `long decode(long x, long y)` otrzymano kod:
```c=
decode: leaq (%rdi,%rsi), %rax
xorq %rax, %rdi
xorq %rax, %rsi
movq %rdi, %rax
andq %rsi, %rax
shrq $63, %rax
ret
```
```c=
long decode(long x, long y) {
long result = x + y; // leaq (%rdi,%rsi), %rax
x = result ^ x; // xorq %rax, %rdi
y = result ^ y; // xorq %rax, %rsi
result = x; // movq %rdi, %rax
result &= y; // andq %rsi, %rax
result = (result >> 63) & 1; // shrq $63, %rax
return result; // ret
}
```
```c=
long decode(long x, long y) {
return ((((x + y) ^ x) & ((x + y) ^ y)) >> 63) & 1;
}
```
## Zadanie 5

`%di` zawiera dwa młodsze bajty %edi
Ponumerujmy bajty w `%edi` jako 1 2 3 4
```assembly=
rorw %di, $8 // 1 2 4 3
rorl %edi, $16 // 4 3 1 2
rorw %di, $8 // 4 3 2 1
movl %edi, %eax
ret
```
Tłumaczenie roll:
```c
(x & 0xFF000000) >> 24 | (x & 0x00FFFFFF) << 8;
```
Tłumaczenie rorl:
```c
(x & 0x000000FF) << 24 | (x & 0xFFFFFF00) >> 8;
```
## Zadanie 6
```assembly=
addq %rsi, %rcx
adc %rdi, %rdx
movq %rcx, %rax
ret
```
https://stackoverflow.com/questions/4153852/assembly-adc-add-with-carry-to-c
## Zadanie 7
Wiemy, że $x = x_1 \cdot 2^{64} + x_0$ oraz $y = y_1 \cdot 2^{64} + y_0$. Wtedy $x*y = (x_1 \cdot 2^{64} + x_0)\cdot (y_1 * 2^{64} + y_0) = x_1\cdot y_1\cdot 2^{128} + (x_1\cdot y_0 + x_0\cdot y_1)\cdot 2^{64} + x_0\cdot y_0$.
Wartość $x_1\cdot y_1\cdot 2^{128}$ jest za duża, więc ją pomijamy.
$x_1=\%rdi$
$x_0=\%rsi$
$y_1=\%rdx$
$y_0=\%rcx$
```
multiply:
movq %rdx, %rax
mulq %rsi
movq %rax, %r8
movq %rdi, %rax
mulq %rcx
addq %rax, %r8
movq %rsi, %rax
mulq %rcx
addq %r8, %rdx
ret
```


## Zadanie 8
Wartości $x$ i $y$ typu `uint64_t` są przekazywane przez rejestry `%rdi` i `%rsi`, a wynik zwracany w rejestrze `%rax`
$$
\begin{equation}
addu(x,y)=
\begin{cases}
ULONG\_MAX & \text{dla } x+y\geq ULONG\_MAX\\
x+y & \text{w p.p.}
\end{cases}
\end{equation}
$$
Najpierw rozwiąż zadanie używając instrukcji skoku warunkowego
`jnc` $\to$ skok, jeśli nie ma przeniesienia, flaga `CF = 0`
```assembly=
addq %rsi, %rdi
jnc jump
movq $ULONG_MAX, %rdi
jump: movq %rdi, %rax
```
Potem przepisz je używając instrukcji `sbb`
`sbb A B`
- Subtraction with Borrow
- działanie $\to$ odejmuje `B` i flagę `CF` od `A`
- wynik przechowuje w `A`
- `A` $\to$ rejestr lub adres pamięci
- `B` $\to$ konkretna wartość, rejestr lub adres pamięci (ale tylko jeśli A również nie jest adresem pamięci).
```assembly=
addq %rsi, %rdi // ustawi flagę CF
sbbq %rax, %rax // %rax = %rax − (%rax + CF)
// %rax = -CF
orq %rdi, %rax // dla %rax = -1 zwróci ULONG_MAX
// dla %rax = 0 zwróci %rdi
```
## Zadanie 9
```cpp
long cmp(uint64_t x, uint64_t y);
```
`%rdi := x` pierwszy argument funkcji.
`%rsi := y` drugi argument funkcji.
Wartość będzie zwracana orzez `%rax`.
Wykorzystywać będziemy **Carry Flag**. Flaga będzie ustawiana przez operację `subq` jeżeli będziemy odejmować większą liczbę od mniejszej.
`adc Src, Dest` - `Dest := Dest + Src + CF`
`sbb Src, Dest` - `Dest := Dest - (Src + CF)`
`neg Dest` - `CF := !(Dest == 0)`, `Dest := -Dest`
```
if(Destination == 0) CF = 0;
else CF = 1;
```
```assembly=
subq %rsi, %rdi // x = x - y
sbbq %rax, %rax
negq %rdi // if x != y: CF := 1
adcq %rax, %rax
ret
```
1. `x > y`:
- `CF := 0 and %rdi != 0`
- `%rax := 0`
- `CF := 1`
- `%rax := 1`
2. `x < y`:
- `CF := 1 and %rdi != 0`
- `%rax := -1`
- `CF := 1`
- `%rax := -1`
3. `x == y`:
- `CF := 0 and %rdi := 0`
- `%rax := 0`
- `CF := 0`
- `%rax := 0`