Assembler for newbies in Low level Programming

Ассемблер для новичков в низкоуровневом программировании.



Для процессора не существует никакой разницы между данными и кодом.

Фон Нейман.

Выпуск 01.

Если после числа стоит h, то число 16-ричное(HEX), если b то бинарное(Binary, в двоичной системе счисления), если d то десятичное(Decimal). Обычно по умолчанию число считается десятичным. А, еще hex числа нам нужны так как любой байт будет соответствовать одному hex числу.

Программы состоят из команд микропроцессора и данных, команды представляют собой бинарный машинный код. Те команды, что мы пишем на ассемблере, преобразуются транслятором в машинный код, или в несколько команд. К примеру mov ax,21 будет выглядеть как B821 а mov bx,2145 преобразуется в BB4521. Чтобы программа выполнилась, необходимо в первую очередь загрузить её в память. Этим у нас занимается ОС, она загружает нашу программу, и передает управление на точку входа (эта та метка начала программы). Программа выполняет свои какието действия, и дает знать операционке что она типа закончила работу. (4Сh функция 21h прерывания).

Прерывания – сигнал процессору, что какое-то устройство требует его внимания. Их разрешили посылать и программам. Т.е. что у нас делается:

вызывается прерывание, и процессор смотрит номер прерывания, 21h – это прерывания закрепленные для использования ДОС-ом. Далее он смотрит значение регистра AH, и вызывает функцию, номер которой лежит в AH. К примеру 09h функция выводит на экран текст, адрес которого лежит в регистре DX.

Вдумчивый читатель задаст вопрос, а собственно говоря где лежат эти функции? Ведь они тоже являются кодом, иначе как бы они смогли что-нибудь делать! А на расположение их указывает 4 байта по адресу получаемому таким образом: 4*N где N -номер прерывания, т.е. 21h находится 4*21h = 84h

Память (RAM или ОЗУ) cостоит их массива однобайтовых ячеек, а то как мы имеем к ней доступ, мы определяем сами. Каждой ячейке мы присваиваем свой номер(0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,10). Это называется физическим адресом. Это конечно удобно, однако подумайте, один регистр может вместить максимальное число FFFFh. Так что-же, память выше этой границы не использовать? Выход был найден в использовании двух регистров для адресации, один регистр содержит адрес сегмента, а другой – адрес внутри этого сегмента (смещение). Соответственно размер сегмента не сожет быть больше FFFFh, или 64kb (65535 байт). Таким образом мы можем получить доступ к памяти до 1 мегабайта.

Значит память у нас разделена на 64-килобайтовые сегменты. Следовательно наша программа (ведь она тоже грузится в память) должна иметь хотя-бы один сегмент.

Примечание: Сегментные регистры должны перед началом работы содержать адреса сегментов, иначе многие команды не будут работать! Команда ASSUME кроме того помещает в регистр CS адрес сегмента кода.

;\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

Title input_char

codeseg segment

ASSUME cs:codeseg,ds:codeseg,ss:codeseg

start:

mov ax,codeseg

mov ds,ax



mov ah,09h

mov dx,offset text

int 21h

mov ah,4Ch

int 21h

text db 'test$'

codeseg ends

end start

;\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

Кстати, гораздо удобнее код, данные и стек размещать в разных сегментах. Директива ASSUME определяет какой сегмент является сегментом кода, какой – данных, какой – стека. (CS-Code Segment сегмент кода, DS-Data Segment сешмент данных, SS -Stack Segment). Следовательно мы в этой програмке все сегменты определяем на codseg, на сегмент кода. Если мы откроем эту прогу (в уже скомпилированном виде, т.е. в exe) в дизассемблере, то увидим вод такую картину(лишнее урезано):



dseg:0000 start proc near

dseg:0000 mov ax, seg dseg

dseg:0003 mov ds, ax

dseg:0005 assume ds:dseg

dseg:0005 mov ah, 9

dseg:0007 mov dx, 10h

dseg:000A int 21h ; DOS - PRINT STRING

dseg:000A ; DS:DX -> string terminated by "$"

dseg:000C mov ah, 4Ch

dseg:000E int 21h ; DOS - 2+ - QUIT WITH EXIT CODE (EXIT)

dseg:000E start endp ; AL = exit code

dseg:000E

dseg:000E ; ---------------------------------------------------------------------------

dseg:0010 db 74h, 65h, 73h, 74h, 24h

dseg:0010 dseg ends

dseg:0010

dseg:0010

dseg:0010 end start

Объясняю, что все это значит. dseg:0000 start proc near -это наша метка (start:)

Да, адреса здесь в байтах, и значит, что команда к примеру mov ah,09h весит 2 байта, следующая команда будет через 2 байта.

Дальше с адреса 0000 по 0003 идет инициализация сегмента данных.

dseg:0005 assume ds:dseg Это подсказка, что теперь в DS содержится адрес текущего сегмента.

dseg:0005 помещаем в ah, число 09h

dseg:0007 помещаем в регистр dx 10h (смещение нашего текста(test$)). Команда offset заставляет транслятор вычислять адрес метки стоящей после него, и подставить реальное значение.

dseg:000A вызов 21h прерывания, судя по комментарию вставленном IDA, печатает на экране строку адрес которой лежит в регистре DX.

dseg:000C помещаем в ah, число 4Ch

dseg:000E вызов 21h прерывания, по комменту IDA выход с кодом выхода, регистр AL содержит код выхода.

dseg:0010 наш текст.В hex виде.



Директива db заставляет транслятор резервировать в тексте программы байт.

Пример:

db 10 ; зарезервирует 1 байт и запишет в него число 10.

db 'hello' ; зарезервирует 5 байт, в которые поместит ASCII коды букв hello

db 10 dup(0) ; зарезервирует 10 байт в которые поместит нулики.



Вот теперь вам пример программы с несколькими сегментами (кода, данных, стека)

title segments

dseg segment

link db 10 dup(0)

db '$'

dseg ends

stseg segment stack

db 20 dup(0)

stseg ends

codseg segment

ASSUME cs:codseg,ds:dseg,ss:stseg

begin:

mov ax,dseg

mov ds,ax

mov ax,stseg

mov ss,ax

mov dx,0000

mov byte ptr link,01 ; помещаем в байт по адресу метки link число 01.





mov ah,09h

int 21h

mov ah,4Ch

int 21h

codseg ends

end begin

Кстати, поскольку нет никакой разницы между данными и кодом, можно сделать самомодифицирующуюся программу.

Задание: Поэксперементируйте с различными цифрами, посмотрите дизасм листинг всех этих прог.

Приложение к рассылке, со списком функций ДОС-а, списком регистров, описанием команд, и многого другого, вы найдете на http://ass3mbler.narod.ru

(оно там обозначено как приложение к статье)

ведущий рассылку Skif_Q

Да пребудет с вами знание!





Хостинг от uCoz