Zadania z terminu zerowego

1. Napisać funkcję asemblerową:
int asm_main(int pierwszy, int drugi)
która sprawdzi, czy oba parametry funkcji są tego samego znaku. Jeżeli pierwszy i drugi są jednocześnie dodatnie lub jednocześnie ujemne funkcja powinna zwrócić wartość 1. Jeżeli pierwszy i drugi mają przeciwne znaki (na przykład pierwszy jest dodatni a drugi ujemny) to funkcja powinna zwrócić 0. Dla ułatwienia zakładamy, że pierwszy i drugi nie będą przyjmowały wartości 0.

2. Napisać funkcję asemblerową:
unsigned int asm_main()
która zwróci liczbę, odpowiadającą tablicy znaków cyfry. Zakładamy – do wyboru – że w tablicy tej znajduje się ile znaków, lub że ciąg cyfr kończy się bajtem o wartości 0. Jeżeli przykładowo cyfry[] = “901” to tablica ta zawiera w praktyce bajty o wartościach 57, 48, 49, 0. Tym samym aby obliczyć liczbę odpowiadającą tej tablicy należy systematycznie pobierać bajty z tablicy, odejmować od nich 48 i tę różnicę dodawać do uprzedniego pośredniego wyniku pomnożonego przez 10, tak aby ostatecznie otrzymać wynik o wartości 901.
(rozwiązanie by R.Radzisz)

3. Napisać funkcję asemblerową:
int asm_main()
która sprawdzi, ile zer kończy binarną reprezentację zmiennej liczba. Jeżeli przykładowo liczba = 96 to jej binarna reprezentacja ma postać:
0000000001100000
Ponieważ liczba ta ma na końcu 5 zer, funkcja powinna zwrócić wartość 5.

1.
C++

1
2
3
4
5
6
7
8
9
10
11
#include
using namespace std;
extern "C" {
int asm_main(int a, int b);
}

int main()
{
int wynik = asm_main(-1,2);
return 0;
}

ASM

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
.386               ;Instrukcje procesora 80386
.MODEL FLAT, C     ;Model rozmieszczenia programu w pamieci (FLAT) i wywolywania funkcji (C)
.CODE              ;Poczatek segmentu przeznaczonego na instrukcje
asm_main PROC

push ebp            ; pobieranie parametrów ze stosu
mov ebp, esp
mov eax, [ebp+8]            ; pierwszy param
mov ebx, [ebp+12]   ; drugi param

cmp eax, -1
jg pierwsza_dodatnia
pierwsza_ujemna: ; pierwsza ujemna
cmp ebx, -1
jg druga_dodatnia
mov eax,1           ; jeżeli obie ujemne wynik 1
jmp koniec

druga_dodatnia:
mov eax,0           ; pierwsza ujemna druga dodatnia wynik 0
jmp koniec

pierwsza_dodatnia: ; pierwsza dodatnia
cmp ebx, -1
jg druga_dodatnia2
mov eax,0
jmp koniec          ; pierwsza dodatnia druga ujemna wynik 0

druga_dodatnia2:
mov eax,1           ;  obie dodatnie wynik 1
jmp koniec

koniec:
pop ebp ;!! wazne
ret             ;Powrot z funkcji
asm_main ENDP
END

2.
C++

1
2
3
4
5
6
7
8
9
10
11
12
13
#include
using namespace std;
extern "C" {
char cyfry[] = "902";
unsigned int ile = 3;
unsigned int asm_main(void);
}

int main()
{
unsigned int wynik = asm_main();
return 0;
}

ASM

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
.386               ;Instrukcje procesora 80386
.MODEL FLAT, C     ;Model rozmieszczenia programu w pamieci (FLAT) i wywolywania funkcji (C)

EXTERN cyfry:BYTE ;Zmienna zadeklarowana w innym module
EXTERN ile:DWORD

.CODE              ;Poczatek segmentu przeznaczonego na instrukcje

asm_main PROC      ;Definicja procedury (funkcji) "asm_main"

mov ebx,0   ;licznik
mov edx,0

mov ecx, ile ; licznik do petli

petla:
mov al, cyfry[ebx*1]    ; pobieranie bajtów po kolei
sub al, 48      ;wynika z treści zadania
imul edx,10     ; jw.
movsx eax, al       ; przeniesienie bajtu do eax

add edx, eax        ; dodanie wyniku pośredniego do wyniku całkowitego
add ebx, 1

loop petla

mov eax, edx

ret             ;Powrot z funkcji; funkcja zwraca eax
asm_main ENDP
END

3.
C++

1
2
3
4
5
6
7
8
9
10
11
12
#include
using namespace std;
extern "C" {
int liczba = 192;
int asm_main();
}

int main()
{
int wynik = asm_main();
return 0;
}

ASM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.386               ;Instrukcje procesora 80386
.MODEL FLAT, C     ;Model rozmieszczenia programu w pamieci (FLAT) i wywolywania funkcji (C)

EXTERN liczba:DWORD ;Zmienna zadeklarowana w innym module

.CODE              ;Poczatek segmentu przeznaczonego na instrukcje

asm_main PROC      ;Definicja procedury (funkcji) "asm_main"
mov ebx, liczba
mov eax, 0   ; licznik

petla:
ror ebx, 1   ; funkcja rotate right zapisuje najmłodszy bit w carry flag więc jeżeli jest 1 w cf przestajemy odliczać
jc koniec    ; jump if carry flag
add eax, 1  ;  eax pełni tutaj funkcje licznika
jmp petla
koniec:

ret             ;Powrot z funkcji; funkcja zwraca eax
asm_main ENDP
END

bonus1.
asm

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
.386                ;Instrukcje procesora 80386
.MODEL FLAT, C     ;Model rozmieszczenia programu w pamieci (FLAT) i wywolywania funkcji (C)
.CODE              ;Poczatek segmentu przeznaczonego na instrukcje
asm_main PROC

push ebp            ; pobieranie parametrów ze stosu

mov ebp, esp
mov eax, [ebp+8]            ; pierwsza liczba
mov ebx, [ebp+12]           ; druga liczba
mov edx, eax

imul eax, edx
imul eax, edx

cmp eax, ebx
jne rozne
mov eax, 1          ; wynik 1
jmp koniec

rozne:
mov eax, 0          ; wynik 0

koniec:

pop ebp ;
ret
asm_main ENDP
END

bonus3.

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
.386                ;Instrukcje procesora 80386
.MODEL FLAT, C     ;Model rozmieszczenia programu w pamieci (FLAT) i wywolywania funkcji (C)

EXTERN liczba:DWORD ;Zmienna zadeklarowana w innym module

.CODE              ;Poczatek segmentu przeznaczonego na instrukcje

asm_main PROC      ;Definicja procedury (funkcji) "asm_main"
mov ebx, liczba
mov eax, 0   ; licznik
mov cx, 32

petla:
shl ebx, 1
jnc brak
add eax, 1 ;eax pełni tutaj funkcje licznika
brak:
loop petla

cmp eax ,1
je rowne
mov eax, 0
jmp koniec

rowne:
mov eax, 1

koniec:
ret             ;Powrot z funkcji; funkcja zwraca eax
asm_main ENDP
END

x3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.386
.MODEL FLAT, C
EXTERN liczba:DWORD
.CODE
asm_main PROC
mov ebx, liczba
mov eax, 0

etykieta:
ror ebx, 1
jnc koniec
add eax, 1
jmp etykieta

koniec:
ret
asm_main ENDP
END