Отправляет email-рассылки с помощью сервиса Sendsay

Ассемблер для начинающих.

  Все выпуски  

Ассемблер для начинающих. выпуск 03.


Информационный Канал Subscribe.Ru

Assembler for newbies in Low level Programming
Ассемблер для новичков в низкоуровневом программировании.


"Тем, кто охвачен враждою и страстью,
Нелегко постичь это ученье.
Страсти предавшись, тьмою объятые,
Они не поймут того, что тонко,
Что глубоко и трудно для постиженья,
Что против теченья их мысли".

Винайя-питака.


Значит у нас три основных сегмента, сегменты кода, данных и стека. По сути сегмент-
это выделенный кусочек памяти размером в 64 кб, однако, при трансляции, часто
(почти всегда если специально не укзывать обратное) все эти три сегмента располагаются
в одном сегменте, т.к. не имеет смысла тратить память и  процессорное время на
то что может быть в одном сегменте. По сути для программиста это не имеет особого
значения, но может в будущем пригодится. К стати, открыв программу в hex редакторе
типа HVIEW ты не увидиш
никакой разницы между сегментами кода, стека и данных.Разве что визуально заметиш
свои команды.
Единственные границы - это границы которые определяются содержанием регистров
cs,ds,ss, т.е. адресные границы.
 Что -же такое стек, и для чего он нужен.
По сути стек- лишь форма организации памяти. Это означает, что заранее известно,
чтo всегда еденицой данных в стеке является слово. т.е. если мы отправили в стек
3 бита к примеру, эти три бита заполнятся, а остальное будет забито нуликами.
Чаще всего стек используется для передачи параметров функциям (процедурам, это
на асме одно и то-же), а в языках высокого уровня, еще и для хранения переменных,
 массивов и т.п.. А так-же для хранения локальных переменных (процедур, функций),
о чем будет упомянуто особо.
Кстати, статические данные всегда хранятся в массиве данных. 
Значит на адрес начала стека указывает регистр SS, на вершину(top) указывает
регистр SP. Что значит вершина стека: это то слово которое было последним добавлено
в стек. Для работы со стеком определены несколько команд, вот две основные команды-
PUSH и POP
Команда PUSH помещает в стек слово. Пример:
Push ax ;помещает содержимое регистра ax в стек
push 77 ; помещает число 77 в стек.

если потом сделать pop ax, в регистре ax будет число 0077.
Т.есть  pop вытаскивает из стека последнее слово, и помещает его в регистр являющийся
операндом этой команды. В данном случае – в ах.

Очень кстати удобно, так как часто бывает что нехватает регистров, или к примеру
 во время работы процедуры изменяются значения нужных нам регистров, а нам надо
из сохранить. Example:
error proc
push dx
push ax

mov ah,09h
mov dx,offset err
int 21h
pop ax
pop dx
ret     ;возврат из процедуры

err db 'ERROR!!!$'
error endp

теперь мы можем вызывать эту процедуру из любой точки программы, не боясь, что
нужные нам значения регистров потеряются.
Так-же со стеком работают команды CALL и RET. CALL - вызов процедуры, она кладет
в стек текущий адрес, и делает jmp на метку процедуры. RET же берет из стека
адрес и переходит на следующую команду после call.
Example:

data segment
db 'in main program',13,10,'$'
perem dw 1 dup(0)
db 'in procedure',13,10,'$'
data ends

stk segment stack
        db 30 dup(0)
stk ends

codseg segment
ASSUME CS:CODSEG,SS:STK,DS:DATA
begin:
        mov ax,data
        mov ds,ax
        mov ax,stk
        mov ss,ax

        mov ah,09h
        mov dx,0

        call func

        int 21h

        mov ah,4ch
        int 21h

func proc
        push ax
        push dx

        mov ax,10
        add ax,44
        mov perem,ax
        mov ah,09h
        mov dx,offset perem
        int 21h
        pop dx
        pop ax

        ret
func endp

codseg ends
 end begin      

Система работы со стеком: наиболее простой аналогией является стопка блинов-FILO
(First In Last Out первым пришел последним ушел), Блин который мы положили последним,
первым мы и снимем. А самый первый блин будет съеден последним :)

 Вот, почему порядок вытаскивания из стека должен быть противоположен порядку
“складывания” в него. Немного похоже на паскальские скобки begin...end,
каждому begin должен соответствовать свой end. Короче:

push ax
push cx
push bx

pop bx
pop cx
pop ax
чтобы получить правильные начальные значения регистров.

Ну и напоследок небольшая програмка, иллюстрирующая свойства стека:

title stack

data segment
        db 10 dup(0)
        db 'BCE PAbOTAET!!!',13,10,'$'
data ends

stackseg  segment stack
        db 40 dup(1)
stackseg ends

codesegm segment
ASSUME CS:codesegm,DS:data,SS:stackseg
begin:
        mov ax,data
        mov ds,ax

        mov ax,stackseg
        mov ss,ax

loo:

        mov ax,77h
        push ax
        mov bp,sp
        cmp [bp],77h
        jl loo
        jg loo

        mov dx,10
        mov ah,09h
        int 21h

        mov ah,01h
        int 21h

        mov ah,4ch
        int 21h
codesegm ends
        end begin

Думаю, что тут даже комментарии излишни, все просто.


Регистр флагов.
Используя команду cmp, а так-же условные jmp-ы (jz,jnz,jl и пр.) вы наверно могли
задуматься, а откуда процессор узнает, например что 4=4 (cmp), когда выполняет
команду jz. Для этих целей существует регистр флагов, в котором каждый бит выполняет
какую-то функцию.
15-12   биты зарезервированы
11      OF (Overflow Flag) флаг переполнения. Поднимается(т.е. устанавливается в
1 
когда результат вычисления превышает допустимые размеры.
10      DF флаг направления
9       IF (Interrupt Flag) флаг прерывания. Если он сброшен(установлен в 0) то процессор
не реагирует на внешние сигналы(прерывания).
8       TF (Trace Flag) флаг трассировки. Если поднят, то после выполнения каждой операции
обращается к спец. прерыванию. Используется в отладчиках.
7       SF флаг знака. Используется при работе со знаковыми числами.
6       ZF (Zero Flag) флаг нуля. Равен 1 если результат действия(сравнения к примеру)
является true, и 0 если false.
5       зарезервирован
4       AF вспомогательный флаг переноса.
3       зарезервирован
2       PF флаг четности.
1       зарезервирован
0       CF флаг переноса. одно из применений – индикация того, что при выполнении
ДОС-функции произошла ошибка.

Вот к примеру, если при сравнении cmp ax,4  ах равен 4 то поднимается ZF, и если
 далее сделать JZ (Jump If Zero Прыг если Нуль, т.е. перейти, если флаг нуля
поднят) то будет произведен jump, а если не равен, то он не будет произведен.
 Короче все условные jump-ы используют регистр флагов. 
Кроме jump-ов, так-же и другие команды, смотрим которые в приложении.


ведущий рассылку Skif_Q.
skif_q@mail.ru
http://ass3mbler.narod.ru – тут все выпуски рассылки, программы, остальное.

Программирование OpenGL, 3D графика, для новичков в программировании.


Subscribe.Ru
Поддержка подписчиков
Другие рассылки этой тематики
Другие рассылки этого автора
Подписан адрес:
Код этой рассылки: comp.soft.prog.asmnewbies
Архив рассылки
Отписаться
Вспомнить пароль

В избранное