ЭВМ и Периферийные устройства лекция 6
Отрицательные числа
Отрицательные числа. Дополнительный код.
Расширение знака
Расширение знака. CBW, CWDE, CWD, CDQ.
Сдвиг
Сдвиги. Логический сдвиг.
Сдвиги. Арифметический сдвиг.
Сдвиги. Циклический сдвиг.
Сдвиги. Циклический сдвиг.
Сдвиги. Двоичная система.
Сдвиги. Инвертирование битов.
Стек. push, pop
Стек. push
Стек. pop
Подпрограммы. Call.
Подпрограммы. Invoke.
Подпрограммы. 2 способа.
Что делает Invoke
Что делает Invoke
Что делает Invoke
Массивы. LEA.
602.00K
Category: programmingprogramming

Отрицательные числа, сдвиги, стек, подпрограммы invoke, массивы в MASM

1. ЭВМ и Периферийные устройства лекция 6

2. Отрицательные числа

Процессор работает только с нулями и единицами. Он понятия не имеет
о том, что такое знак числа.
Поэтому идут на соглашение – пусть старший бит в обозначает знак.
Если старший бит числа равен 1, то число считается отрицательным.
Если старший бит числа равен 0, то число считается положительным.
7
1
0
6
0
1
Разряды Bin
5 4 3 2
0 1 0 0
1 0 1 1
Число Dec
1
1
1
0
0
0
–110
+110

3. Отрицательные числа. Дополнительный код.

Чтобы превратить положительное число в отрицательное, нужно
инвертировать число и добавить к результату единицу.
110d (в двоичной системе это число 01101110b). Тогда
Исходное число
Инверсия
Прибавляем 1
0110
1001
1001
1110
0001
0010
Сумма положительного и отрицательного даёт 0. Проверим:

4. Расширение знака

Порой требуется поместить число в более просторный регистр.
Например байтовое число из al растянуть на весь ax (2 байта). Или 2байтовое из ax растянуть на eax (4 байта). Эта операция называется
расширением знака.
Для расширения положительного числа нужно старшие разряда
заполнить нулями.
Для расширения отрицательного числа старшие разряды нужно
заполнить единицами.
15
Разряды Bin дополненные
14
13
12
11
10
7
Разряды Bin
6 5 4 3 2
1
0
Число
Dec
9
8
1
1
1
1
1
1
1
1
1
0
0
1
0
0
1
0
–110
0
0
0
0
0
0
0
0
0
1
1
0
1
1
1
0
+110

5. Расширение знака. CBW, CWDE, CWD, CDQ.

CBW (Convert Byte to Word) расширяет число в AL до AX.
CWDE (Convert Word to Doubleword) расширяет число в AX до EAX.
CWD (Convert Word to Doubleword) расширяет число в AX до DX:AX.
CDQ (Convert Doubleword to Quadword) раширяет EAX до EDX:EAX
Вышеперечисленные команды не имеют параметров и не выставляют
флаги.

6. Сдвиг

Специальная операция изменяющая число, путем передвижения
ноликов или единичек в числе.
Существую 3 вида сдвигов:
• Логический – просто сдвиг. Вдвигаемые (вносимые) разряды
всегда нули;
• Арифметический – сдвиг с охранением знака. При сдвиге вправо
Вдвигаемые (вносимые) слева разряды равны значению
знакового бита. Сдвиг влево аналогичен логическому сдвигу, то
есть слева всегда вдвигаются (вносятся) нули;
• Циклический – выталкиваемые разряды коварно вылезают с
другой стороны числа. То есть те разряды, которые были
выдвинуты справа, вдвигаются слева и наоборот;

7. Сдвиги. Логический сдвиг.

Логический свдиг – новые биты заполняются нулями, ушедшие
(выдвинутые) исчезают.
SHL операнд, количество_сдвигов
SHR операнд, количество_сдвигов
SHL и SHR сдвигают биты операнда (регистр/память) влево или
вправо соответственно на указанное число разрядов:
; al =
01011011 (двоичное)
shr al, 3 ; al= 00001011
Это означает: сдвиг всех битов регистра al на 3 разряда вправо.
Так что al станет 00001011.
Биты слева заполняются нулями, а биты справа выдвигаются
(исчезают). Последний выдвинутый бит, становится значением
флага переноса CF.

8. Сдвиги. Арифметический сдвиг.

Арифметический сдвиг – сдвиг с сохранением знака
SAL операнд, количество_сдвигов
SAR операнд, количество_сдвигов
SAL и SAR сдвигают биты операнда (регистр/память) влево или
вправо с сохранением знака соответственно на указанное число
разрядов. С сохранением знака, то есть при сдвиге влево
вдвигаются нули, а при сдвиге вправо, вдвигается значение
старшего разряда (знаковый бит).
;al = 10100110
sar al, 3
;al = 11110100
sar al, 2
;al = 11111101
;bl = 00100110
sar bl, 3
;bl = 00000010
Последний выдвинутый бит, становится значением флага переноса CF.

9. Сдвиги. Циклический сдвиг.

Циклический сдвиг – сдвиг с выдвижением выдвинутых разрядов с
другой стороны числа.
rol операнд, количество_сдвигов ; циклический сдвиг операнда влево
ror операнд, количество_сдвигов ; циклический сдвиг операнда вправо
rcl операнд, количество_сдвигов ; циклический сдвиг операнда влево через флаг
переноса
rcr операнд, количество_сдвигов ; циклический сдвиг операнда вправо через флаг
переноса
Операнд
бит
7
1
бит
6
0
бит
5
0
ror операнд,3
Результат
0
1
1
бит
4
1
бит
3
1
бит
2
0
бит
1
1
бит
0
1
1
0
0
1
1
1
0
0
1
1
выдвигается
011

10. Сдвиги. Циклический сдвиг.

ROL и ROR работают просто. То есть выдвигаемые биты появляются с
другой стороны числа. Последний выдвинутый бит оказывается в итоге во
флаге CF.
RCL и RCR в отличии от ROL и ROF работаю хитрее. Они выполняют
сдвиг через флаг CF. То есть выдвинутое значение попадает во флаг
CF(это привычно), но не вдвигается с другой стороны числа. Однако
одновременно при этом значение, уже лежавшее в CF, не пропадает, а
вдвигается с другой стороны числа.
Флаг CF в данном случае работает как дополнительный разряд,
приклеившийся к числу (для RCL – слева, для RCR - справа).

11. Сдвиги. Двоичная система.

При умножении на степень числа
2 (2,4,8 и т.д.) более эффективным является сдвиг влево на требуемое
число битов.
Умножение значения из ax на 2:
sal ax,1
Умножение значения из ax на 8:
sal ax,3
Деление значения из ax на 2:
sar ax,1
Деление значения из ax на 8:
sar ax,3
При делении, соответственно, сдвиг производится вправо. В данном
случае если вы работаете со знаковыми числами, то сдвиг должен быть
арифметическим, чтобы сохранить знак.

12. Сдвиги. Инвертирование битов.

Задача: дано некое однобайтное число. Нужно инвертировать его биты.
То есть в итоге первый бит должен стать восьмым, второй – седьмым и
так далее.
mov CX,8 ; Толкаем 8 бит
mov AL,[число] ; однобайтовые число помещает в AL
xor BL,BL ; обнулим регистр под результат
repeat:
rcr AL,1 ; выталкиваем правый бит во флаг CF
rcl BL,1 ; заталкиваем его из флага CF в результат
loop repeat ; и так четыре раза
mov [результат],BL ; ответ в переменную

13. Стек. push, pop

Процессор имеет аппаратную поддержку стека. При этом стек,
хранится в оперативной памяти
push – поместить значение (2 или 4 байта) в стек
pop – достать значение из стека (2 или 4 байта)
push
Стек растёт в сторону уменьшения адресов памяти.
Значение, помещенное в стек последним,
извлекается первым.
Регистр ESP хранит адрес вершины стека.
Стек используется для хранения параметров процедур
И их локальных переменных.
Естественно, вы можете использовать стек в своих целях,
но вы отвечаете за его содержимое
pop

14. Стек. push

Пусть стек находится в следующем состоянии.
(стек здесь заполнен нулями, но в действительности это не так, как
здесь). ESP стоит в том месте, на которое он указывает)
mov ax, 4560h
push ax
mov ax, 0FFFFh
push ax

15. Стек. pop

С момента предыдущего слайда стек находится в таком состоянии
pop edx
edx теперь равно 4560FFFF
Обратите внимание, что команда pop не чистит стек

16. Подпрограммы. Call.

Процедуры задаются директивами proc и endp. Proc обозначает
начало процедуры, а endp конец процедуры. Вот пример
объявления
процедуры:
SomeProc proc
...ещё код...
Ret ; обязательно
SomeProc endp
Вызов процедуры
Call SomeProc
Параметры процедуры должны быть выложены в стек перед её
вызовом в обратном порядке.

17. Подпрограммы. Invoke.

Существует улучшенный способ вызова и задания процедур.
Invoke <функция>, <параметр1>, <параметр2>, <параметр3>
Для этого нужно сначала объявить прототип:
PROTO STDCALL testproc :DWORD, :DWORD, :DWORD
STDCALL указывать необязательно. DWORD тип. Возможны
типы, например WORD, BYTE и т. д..
Вызов процедуры:
Invoke testproc, 1d, 2d, 3d,
При этом ещё на этапе компиляции будут проверено количество
параметров и их тип, что подстрахует вас от ошибок.

18. Подпрограммы. 2 способа.

MyProc PROTO :DWORD,:DWORD
.code
MySimpleProc proc
mov eax, dword ptr [esp+4]
mov ecx, dword ptr [esp+8]
ret
MySimpleProc endp
MyProc proc myparam1:DWORD, myparam2:DWORD
LOCAL var1:DWORD ; локальная переменная 1
LOCAL var2:BYTE,var3:WORD ; локальные переменные 2 и 3
mov eax,myparam1
mov ecx,myparam2
ret
MyProc endp
start:
xor eax,eax
xor ecx,ecx
push 2h
push 1h
call MySimpleProc
invoke MyProc ,1h,2h
invoke ExitProcess, NULL; Завершить процесс
end start

19. Что делает Invoke

Возьмём часть программы:
MyProc PROTO :DWORD,:DWORD
.code
MyProc proc myparam1:DWORD, myparam2:DWORD
LOCAL var1,var2:DWORD ; локальные переменные 1 и 2
mov eax,myparam1
mov ecx,myparam2
mov var1,eax
mov var2,ecx
ret
MyProc endp
start:
xor eax,eax
xor ecx,ecx

invoke MyProc ,1h,2h
invoke ExitProcess, NULL; Завершить процесс
end start

20. Что делает Invoke

Вот, что происходит:
MyProc PROTO :DWORD,:DWORD
.code
MyProc proc myparam1:DWORD, myparam2:DWORD
push ebp
mov ebp, esp
add esp, -8h; = LOCAL var1,var2:DWORD ;
mov eax, DWORD PTR [EBP+8]; = mov eax,myparam1
mov ecx, DWORD PTR [EBP+0C]; = mov ecx,myparam2
mov DWORD PTR [EBP-4],eax; = mov var1,eax
mov DWORD PTR [EBP-8],ecx; = mov var2,ecx
Leave; = mov esp,ebp
;
pop ebp
ret; pop eip
MyProc endp
start:
xor eax,eax
xor ecx,ecx

push 2h
push 1h
call MyProc;= invoke MyProc ,1h,2h
invoke ExitProcess, NULL; Завершить процесс
end start

ebp+8,esp var2
ebp +4
var1
ebp
ebp
Адрес возврата
ebp +8
myparam1
ebp +0C
myparam2

21. Что делает Invoke

При вызове процедуры через Invoke происходит следующее:
1) Параметры процедуры помещаются с стек в обратном порядке;
2) Вызывается call для процедуры. В этот момент в стек заносится
значение EIP (это и будет адресом возврата).
Внутри процедуры происходит следующее:
1) В стек помещается содержимое EBP;
2) Содержимое ESP помещается в EBP;
3) В стек записываются локальные переменные в порядке
следования;
4) Выполняется основная часть процедуры
Перед выходом из процедуры происходит следующее:
1) Вызывается команда Leave. Она эквивалента помещению значения
EBP в ESP (в этот момент вершина стека уходит за локальные
переменные). Затем из стека выталкивается сохранённое значение
EBP в EBP.
2) Вызывается команда ret в ходе работы которой вершина стека
отодвигается за передаваемые параметры и происходит извлечения
адреса возврата из стека и помещение его в EIP.

22. Массивы. LEA.

LEA (Load Effective Address) – команда помещения адреса.
LEA приемник, источник
Команда похожа на mov. Однако она используется исключительно
для помещения адреса в указанный регистр.
Приемник – регистр, куда помещается адрес. Именно регистр.
Источник – источник адреса (то есть у чего берем адрес). Под
источником подразумевается память.
English     Русский Rules