ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ АВТОНОМНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ
«Национальный исследовательский университет ИТМО»
Факультет безопасности информационных технологий
Дисциплина:
«Информатика»
ОТЧЕТ ПО ЛАБОРАТОРНОЙ РАБОТЕ №2
Поразрядные и логические операции.
Выполнил:
Студент группы N3146
ФИО
Кудряшов Павел Сергеевич
Проверил:
Грозов В.А.
Санкт-Петербург
2021г.
Вариант 6
Задание: Старшую тетраду каждого байта числа заменить результатом операции «стрелка Пирса» старшей и младшей тетрад, а младшую тетраду – результатом операции «штрих Шеффера» старшей и младшей тетрад исходного байта.
Блок-схема:
Текст на Си:
#include // стрелка Пирса : (x | y);
// штрих Шеффера : (x & y); void print_bin(int, int); int main() { unsigned int num = 0xD3;
unsigned int clearbyte = 0xFF;
unsigned int tetrada = 0xF;
unsigned int firsttet = 0x0;
unsigned int secondtet = 0x0;
unsigned int tmp = 0x0;
print_bin(num, 1); for (int i = 0; i < 4; i++) { // бежим по каждому байту
firsttet = (num & (tetrada << i * 8)) >> i * 8; // заносим младшую тетраду
secondtet = (num & (tetrada << i * 8 + 4)) >> i * 8 + 4; // заносим старшую тетраду
tmp = firsttet; // сохраняем младшую тетраду
firsttet = ((secondtet & tmp)) & tetrada;// преобразуем младшую тетраду по штриху Шеффера
secondtet = ((secondtet | tmp)) & tetrada;// преобразуем старшую тетраду по стрелке Пирса
num = (num & ((clearbyte << i * 8))) | (firsttet << i * 8) | (secondtet << i * 8 + 4); // обнуляем байт с которым работали и заносим старшую и младшую тетрады.
}
print_bin(num, 1);
return 0;
}
// функция для вывода нужного кол-ва байтов
void print_bin(int a, int byte) {
for (int i = byte * 8 - 1; i >= 0; i--) printf("%d", (a & (1 << i)) >> i);
printf("\n");
}
Текст на ассемблере:
section .data
; для вывода числа
one db "1"
zero db "0"
binlen equ $-zero
enofl db 0xA
; для алогритма
num dd 0xA2
clearbyte dd 0xFF
tetrada dd 0xF
section .bss
; для вывода числа
numb resb 4
iter resb 1
cutter resb 1
; для алогритма
firsttet resb 4
secondtet resb 4
tmp resb 4
byte_cnt resb 1
section .text
;вывод числа
printZ:
mov eax, 4
mov ebx, 1
mov ecx, zero
mov edx, binlen
int 80h
ret
printO:
mov eax, 4
mov ebx, 1
mov ecx, one
mov edx, binlen
int 80h
ret
printE:
mov eax, 4
mov ebx, 1
mov ecx, enofl
mov edx, binlen
int 80h
ret
printN:
cmp eax, 1
jl zeroN
call printO
jmp oneN
zeroN:
call printZ
oneN:
ret
printX:
mov byte[iter], 8
whileX:
cmp byte[iter], 1
jl endX
mov cl, byte[iter]
dec cl
mov eax, dword[numb]
shr eax, cl
mov byte[iter], cl
mov byte[cutter], 1
call cutnum
call printN
jmp whileX
endX:
call printE
ret
cutnum:
mov ebx, eax
mov cl, byte[cutter]
shr ebx, cl
shl ebx, cl
xor eax, ebx
ret
;алгоритм
global _start
_start:
; вывод начального числа
mov eax, dword[num]
mov dword[numb], eax
call printX
; записываем значение счетчика
mov al, 0
mov byte[byte_cnt], al
loop_start:
; условие цикла
cmp al, 4
jge ex
; записываем сдвиг i * 8 в cl
mov al, byte[byte_cnt]
mov cl, 8
mul cl
mov cl, al
; для младшей тетрады
; помещаем наше число в eax
mov eax, dword[num]
; tetrada << i * 8 -> заносим в ebx
mov ebx, dword[tetrada]
shl ebx, cl
; num & ebx заносим в eax
and eax, ebx
; eax >> i * 8 заносим в firsttet
shr eax, cl
mov dword[firsttet], eax
; для старшей тетрады
; помещаем наше число в eax
mov eax, dword[num]
; записываем сдвиг i * 8 + 4 в cl
add cl, 4
; tetrada << i * 8 + 4 -> заносим в ebx
mov ebx, dword[tetrada]
shl ebx, cl
; num & ebx заносим в eax
and eax, ebx
; eax >> i * 8 + 4 заносим в secondtet
shr eax, cl
mov dword[secondtet], eax
; сохраняем в tmp младшую тетраду
mov eax, dword[firsttet]
mov dword[tmp], eax
; преобразуем младшую тетраду по штриху Шеффера
; (secondtet & tmp) -> помещаем в eax
mov eax, dword[secondtet]
mov ebx, dword[tmp]
and eax, ebx
not eax
; eax & tetrada (чтобы оставить только одну тетраду) помещаеме в firsttet
mov ebx, dword[tetrada]
and eax, ebx
mov dword[firsttet], eax
; преобразуем старшую тетраду по стрелке Пирса
; (secondtet | tmp) -> помещаем в eax
mov eax, dword[secondtet]
mov ebx, dword[tmp]
or eax, ebx
not eax
; eax & tetrada (чтобы оставить только одну тетраду) помещаем в secondtet
mov ebx, dword[tetrada]
and eax, ebx
mov dword[secondtet], eax
; запись изменения числа
; сначала обнуляем байт с которым работали
; запишем сдвиг i * 8 в cl
mov al, byte[byte_cnt]
mov cl, 8
mul cl
mov cl, al
; запишем наше число в eax
mov eax, dword[num]
; создадим инвертированную маску 0xFF, чтобы обнулить интересующий нас байт ((clearbyte << i*8)) и запишем ее в ebx
mov ebx, dword[clearbyte]
shl ebx, cl
not ebx
; обнулим интересующий нас байт (num & ebx)
and eax, ebx
; установим младшую тетраду на место в нулевом байте
; сдвигаем нашу тетраду на нужное место
mov ebx, dword[firsttet]
shl ebx, cl
; и добавляем к нашему числу
or eax, ebx
; установим старушую тетраду на место в байте с нашей измененной тетрадой
; изменим на сдвиг на 4
add cl, 4
; сдвигаем нашу тетраду на нужное место
mov ebx, dword[secondtet]
shl ebx, cl
; и добавляем к нашему числу
or eax, ebx
mov dword[num], eax
; переход
mov al, byte[byte_cnt]
inc al
mov byte[byte_cnt], al
jmp loop_start
ex:
; вывод
mov eax, dword[num]
mov dword[numb], eax
call printX
; выход
mov eax, 1
xor ebx, 0
int 0x80
Дизассемблерный листинг
Main:
0000000000001169 <main>: 1169: f3 0f 1e fa endbr64 116d: 55 push rbp 116e: 48 89 e5 mov rbp,rsp 1171: 48 83 ec 20 sub rsp,0x20 1175: c7 45 e4 d3 00 00 00 mov DWORD PTR [rbp-0x1c],0xd3 117c: c7 45 ec ff 00 00 00 mov DWORD PTR [rbp-0x14],0xff 1183: c7 45 f0 0f 00 00 00 mov DWORD PTR [rbp-0x10],0xf 118a: c7 45 f4 00 00 00 00 mov DWORD PTR [rbp-0xc],0x0 1191: c7 45 f8 00 00 00 00 mov DWORD PTR [rbp-0x8],0x0 1198: c7 45 fc 00 00 00 00 mov DWORD PTR [rbp-0x4],0x0 119f: 8b 45 e4 mov eax,DWORD PTR [rbp-0x1c] 11a2: be 01 00 00 00 mov esi,0x1 11a7: 89 c7 mov edi,eax 11a9: e8 dc 00 00 00 call 128a <print_bin> 11ae: c7 45 e8 00 00 00 00 mov DWORD PTR [rbp-0x18],0x0 11b5: e9 b0 00 00 00 jmp 126a <main+0x101> 11ba: 8b 45 e8 mov eax,DWORD PTR [rbp-0x18] 11bd: c1 e0 03 shl eax,0x3 11c0: 8b 55 f0 mov edx,DWORD PTR [rbp-0x10] 11c3: 89 c1 mov ecx,eax
…
0000000000002058 <__FRAME_END__-0x124>: 2058: 14 00 adc al,0x0 205a: 00 00 add BYTE PTR [rax],al 205c: 00 00 add BYTE PTR [rax],al 205e: 00 00 add BYTE PTR [rax],al 2060: 01 7a 52 add DWORD PTR [rdx+0x52],edi 2063: 00 01 add BYTE PTR [rcx],al 2065: 78 10 js 2077 <__GNU_EH_FRAME_HDR+0x6f> 2067: 01 1b add DWORD PTR [rbx],ebx 2069: 0c 07 or al,0x7 206b: 08 90 01 00 00 14 or BYTE PTR [rax+0x14000001],dl 2071: 00 00 add BYTE PTR [rax],al 2073: 00 1c 00 add BYTE PTR [rax+rax*1],bl 2076: 00 00 add BYTE PTR [rax],al 2078: 08 f0 or al,dh 207a: ff (bad) 207b: ff 2f jmp FWORD PTR [rdi] 207d: 00 00 add BYTE PTR [rax],al 207f: 00 00 add BYTE PTR [rax],al 2081: 44 07 rex.R (bad) 2083: 10 00 adc BYTE PTR [rax],al 2085: 00 00 add BYTE PTR [rax],al 2087: 00 24 00 add BYTE PTR [rax+rax*1],ah 208a: 00 00 add BYTE PTR [rax],al 208c: 34 00 xor al,0x0 208e: 00 00 add BYTE PTR [rax],al 2090: 90 nop 2091: ef out dx,eax 2092: ff (bad) 2093: ff 30 push QWORD PTR [rax] 2095: 00 00 add BYTE PTR [rax],al 2097: 00 00 add BYTE PTR [rax],al 2099: 0e (bad) 209a: 10 46 0e adc BYTE PTR [rsi+0xe],al 209d: 18 4a 0f sbb BYTE PTR [rdx+0xf],cl 20a0: 0b 77 08 or esi,DWORD PTR [rdi+0x8] 20a3: 80 00 3f add BYTE PTR [rax],0x3f 20a6: 1a 3a sbb bh,BYTE PTR [rdx] 20a8: 2a 33 sub dh,BYTE PTR [rbx] 20aa: 24 22 and al,0x22 20ac: 00 00 add BYTE PTR [rax],al 20ae: 00 00 add BYTE PTR [rax],al 20b0: 14 00 adc al,0x0 20b2: 00 00 add BYTE PTR [rax],al 20b4: 5c pop rsp 20b5: 00 00 add BYTE PTR [rax],al 20b7: 00 98 ef ff ff 10 add BYTE PTR [rax+0x10ffffef],bl ...
Краткий анализ по результатам сравнения:
Дизассемблированная программа взаимодействует со стеком и сдвиги реализуются не в цикле, в отличие от программы написанной на ассемблере, а «в тупую».
|