Старый 24.03.2011, 11:20   #1
Vollkorn
 
Регистрация: 24.03.2011
Сообщений: 16
Репутация: 5
Post Ассемблер для самых маленьких.

Ассемблер для самых маленьких


План:
1) Введение
2) Пару слов про асм
3) Tasm
4) Регистры, сегменты
5) Команды асма
6) Первая прога
7) Разбор программы
8) Функции
9) Стек
10) Команды перехода
11) Циклы
12) Процедуры
13) Include
14) Написание программы, используя полученные знания
15) Вывод

Начнем.
I Введение
Здравствуйте, РДотовцы. Эту статью я хочу посвятить тем, кто хочет изучать ассемблер (т.е. тем, кто еще не начал, ну или начал, но совсем чуть-чуть). На нашем форуме я не обнаружил ни одной статьи для начинающих учить ассемблер. Есть много постов, где выкладывают книги по асму, так же есть тема, где новички задают вопросы, и статья про cracking, но именно статьи про программирование на асме для новичков нет. Именно это побудило меня её написать. Для начала я хочу сказать, что эта статья только для новичков, так как в ней нету ничего сложного. Просто, например, когда я начинал учить асм, при прочтении книжек я много чего не понимал, почему это именно сюда и так далее. В этой статье я же постараюсь объяснить как можно более простым языком, что к чему. И последнее во введении, я бы написал, что это моя первая статья, и что я новичок, и что не надо тапками кидать, но меня это жутко бесит, поэтому исправляйте и дополняйте меня пожалуйста, но не обзывайтесь, если можете... Это немного обидно)

II Пару слов про асм

Язы́к ассе́мблера (в отечественных источниках, также автокод) — язык программирования низкого уровня, мнемонические команды которого (за редким исключением) соответствуют инструкциям процессора вычислительной системы. Трансляция программы в исполняемый машинный код производится ассемблером (от англ. assembler - сборщик) - программой-транслятором, которая и дала языку ассемблера его название. (источник Википедия)

III Tasm

Что нам понадобится. Tasm.exe (сам ассемблер), tlink.exe (линковщик), rtm.exe. Вот этих 3 программок хватит. В конце статьи я выложу ссылки на эти программки. Думаю все уже догадались, что всё мы будем делать в Tasm'е) И хоть многие говорят, что Tasm фигня, и т.д., ИМХО ТАСМ -- удобная штука. Вобщем я дам толчок, а дальше Вы уже сами решайте какой ассемблер Вам использовать. Чтобы было удобнее компилировать программы, можете написать небольшой *.bat файл, с содержанием, подобным этому:

bin/tasm название_файла.asm > asm_log.txt
bin/tlink название_файла.obj > link_log.txt


Думаю не сложно догадаться, что этот файл делает =)

IV Регистры, сегменты
Наверно большинство тех, кто сейчас это читает, знают, что почти всё в программировании на ассемблере связано с регистрами.
Прежде всего нужно знать, что регистр -- это сверхбыстрая оперативная память (СОЗУ) внутри процессора. Различают несколько видов регистров: регистры общего назначения (eax/ax/ah/al и т.д.), сегментные регистры (cs, ss, ds и т.д.) и регистры состояния и управления (eip/ip, eflags/flags).

Регистры общего назначения используются для хранения промежуточных данных, таких как: операдны* логических и арифметических операций, указатели на ячейки памяти и так далее. Примером могут послужить следующие регистры:

регистр-аккумулятор (EAX) -- применяется для хранения промежуточных данных (немного позже Вы увидите как он используется);
базовый регистр (EBX) -- применяется для хранения базового адреса некоторого обьекта в памяти (если не поняли, особо не думайте об этом =) );
регистр-счетчик (ECX) -- регистр используется в основном для организации циклов (о циклах будет рассказано позже);
регистр данных (EDX) -- так же как и регистр EAX, хранит промежуточные данные.

Среди всех регистров общего назначения, хочется уделить немного больше внимания регистру ESP. Его не стоит использовать для хранения промежуточных данных, так как в нем хранится указатель на вершину стека (про стек будет дальше).
Еще хочется отметить, что регистры общего назначения разделяются на несколько меньших, ну... вобщем вот пример:
EAX (регистр-аккумулятор) -- 32 бита, его 16-ти байтный регистр -- AX, который, в свою очередь, разделяется на регистры AH и AL, по 8 байт. (EBX/BX/BH/BL; ECX/CX/CH/CL и т.д.).

Сегментные регистры. В процессорах Intel поддерживается сегментная организация программы. Любая программа состоит из трех регистров: стека, данных и кода. К каждому сегменту относится определённый регистр. Всего существует 6 сегментных регистров: CS, SS, DS, ES, GS, FS.
Сегмент кода -- думаю не сложно догадаться, что именно в этом сегменте содержатся все команды программы =) Особо заморачиваться в начале с этим не надо, просто запомните, что сегменту кода соответствует регистр CS. Что с этим делать я покажу позже.
Сегмент данных -- тут содержатся данные, которые обрабатываются командами, которые находятся в сегменте кода. Сегменту данных соответствует регистр DS.
Сегмент стека -- про стек расскажу чуть позже, пока запомните, что сегменту стека соответствует регистр SS.
Дополнительный сегмент данных -- думаю название говорит само за себя, особо об этом сегменте не думайте. Этому сегменту соответствуют остальные сегментные регистры (ES, GS, FS).

Регистры состояния и управления. В процессор включены два регистра, которые содержат информацию о самом процессоре, и о программе, которая сейчас выполняется.
Регистр-указатель -- EIP/IP;
регистр флагов -- EFLAGS/FLAGS.
С помощью этих регистров можно управлять состоянием процессора. Тут можно много чего писать, так что если Вам, дорогой читатель, интересно, прочитайте сами.

*операнд -- это такая штука, обозначающая объекты, над которыми производятся действия.

V Команды ассемблера

Думаю те, кто читает эту статью не раз видели ассемблер "в лицо" ) Система команд в этом языке программирования не так сложна, как кажется. Главное запомнить, что в конце каждой строки не обязательно ставить точку с запятой (хотя это может только у меня такая проблемма после си), так как точка с запятой -- это комментарии. Ни для кого не секрет, что внутри компьютера всё записывается как нули и единички (образно говоря), т.е. в двоичном коде. Программирования первых компьютеров именно так и осуществлялось, с помощью только нулей и единиц. Вскоре люди поняли, что это не очень удобно использовать только нолики и единички, поэтому был придуман язык ассемблера, как симолический аналог машинного языка. Отсюда можно сделать вывод, что машинные команды -- это определенно сформированная последовательность нулей и единиц. Что бы было более понятно, приведу пример самой распространенной команды:
mov ebx, eax*
Эта команда копирует содержимое регистра eax в регистр ebx.
Такая же машинная команда будет выглядеть так:
8B D8
Значение 8B -- код операции. Вот еще один пример:
mov ecx, 128
Эта команда записывает в регистр ecx десятичное число 128. Такая же машинная команда выглядет так:
B9 00000080
Как вы видите, несмотря на то, что команда в обеих примерах одна и та же (MOV), коды машинных команд разные. Отсюда можно сделать вывод, что большинство команд ассемблера могут по разному переводится в машинные команды, это зависит от операндов, с которыми они работают.

*mov приемник, источник. Запомните эту команду, она вам очень понадобится.

VI Первая программа

Итак, пришло, наконец-то, время для написания нашей первой программы. Это будет самая простая программка "Hello Antichat!". Думаю вы поняли, что она будет делать (кто не понял, объясняю, это программка будет выводить сообщение "Hello Antichat!").
Я сразу выложу вам код, а после него мы разберем эту программку.

Код:
MODEL SMALL              		  ; Объявляем модель памяти              
                STACK 256    		 ; Объявляем размер стека        
DATASEG                  			 ; Начало сегмента данных          
          msg db 'Hello Antichat! $'              ; создаем переменную msg с текстом "Hello Antichat!"
CODESEG                     		 ; Начало сегомента кода
start:                            			 ; "вход в главную часть"
          mov ax, @data    			 ; связываем сегмент данных 
          mov ds, ax         			 ; с регистром ds 
          mov dx, offset msg 		 ; в регистр dx аддрес переменной msg
          mov ah, 09h     			 ; в регистр ah 09h
          int 21h              			 ; прерывание №21
          mov ah, 1h                                   ; в регистр ah - 1h
          int 21h				 ; прерывание 21
          mov ah, 04ch     			 ; в регистр ah 04ch
          int 21h              			 ; прерываение 21
end start				 ;закончить "главную часть"
VII Разбор программы

Итак, теперь по порядку.
1 строка -- эта команда определяет модель сегментации программы, чтоб сильно Вас не нагружать скажу в двух словах, для небольших программок (а мы пока что такие и пишем), используйте модель SMALL (т.е. код занимает один сегмент, данные объеденены в одну группу с именем DGROUP.) В конце статьи я укажу ссылки, и литературу, где можно об этом прочитать.
2 строка -- в комментарии уже сказал, добавить нечего, объявляем размер стека
4 строка -- создаем переменную msg типа db. На этом мне бы хотелось немного остановится. Совсем капельку. Существует три типа переменных db (Data Byte), dw (Data Word) и dd (Data Doubleword). Что ж, я, например, в большнистве случаев использую db и, пока-что, в начале обучения, советую тоже использовать db. Вы спросите, зачем знак доллара в конце строки? Я отвечу, знак доллара мы пишем, чтоб можно было использовать удобную функцию ассемблера для вывода строки. Об этом я скажу позже.
7-8 строка -- помните я говорил, что существуют сегментные регистры, и что каждый из них соответствует определенному сегмунту? Так вот, в этих двух строках, используя промежуточный регистр ax, вы записываем в регистр ds физический адресс сегмента данных.
9 строка -- в регистр dx помещаем адресс переменной msg, почему именно так, я расскажу слудеющем разделе.
10 строка -- в ah записываем 09h, зачем это делать, я опять таки расскажу в следующем разделе.
11 строка -- операция прерывания дос. Int сокращенно от interupt, что переводится как прерывание.
12 строка -- в регистр ah 04ch
13 строка -- операция прерывания
14 строка -- закончить "главную часть"
Думаю стало немного более понятно.

VIII Функции

Когда я начинал учить ассемблер, мне было не понятно, почему именно те числа помещаем именно в тот регистр, и почему именно то, помещаем сюда. Объясняю для таких, как я =)
В ассемблере тоже есть функции, с некоторыми из них мы встречались в шестом разделе, когда писали первую программку. Давайте вспомним:

1) mov dx, offset msg
mov ah, 09h
int 21h
2) mov ah, 04ch
int 21h


Итак, как я уже говорил, в ассемблере существуют функции. В нашем случае первая функция -- это вывод информации на экран. Вторая -- выход из программы. Давайте разберем подробней несколько функций.

Функция вывода строки на экран:
в ah надо поместить 09h, а в dx то, что надо выводить, в нашем случае, мы поместили в регистр dx адресс нашей строки, так как наша строка слишком длинная для помещения её в этот регистр. Что бы использовать функцию 09h, надо, чтоб в конце строки был символ доллара (вот мы и узнали зачем он там).

Функция выхода из программы:
в ah нужно поместить значение 04ch, и вызвать операцию прерывания.

Eщу одна функция вывода строки (мы её не использовали, так как она сложнее той, что мы использовали):
в регистр dx -- то, что надо вывести
в регистр cx -- количество выводимых символов
в регистр bx -- устройство, куда записывать, в нашем случае 1
в регистр ah -- 40h, сам код этой функции

Считать символ (там много чего запутано, будем пока его использовать, что после выполения программы, окно доса не закрывалось, а ждало пока мы нажмем клавишу)
в ah -- 1h
в al -- появится символ, который вы ввели.


Ну...я думал дать еще пару функций, потом передумал, так как решил, что они вам пока не нужны =)
Как вы уже заметили, после того, как всё помещено по нужным регистрам, нудо вызвать прерывание. Запомните это.
Такс, с функциями слегка разобрались. Пойдем дальше.

IX Стек

Нууу, стек -- это такая область памяти. Адресацией в стеке занимается регистр es. В основном, стек используется для временного хранения содержимого регистров. Стоит помнить, что именно для ВРЕМЕННОГО. Стек работает по принципу LIFO, Last In Firs Out. Т.е. последний элемент, который положили в стек, должен первым оттуда выйти. Примером может послужить обойма автомата. Думаю все когда нибудь держали в руках обойму от автомата. В школе, в старших классах на подготовке к армии должны были. Первая пуля, которая была туда засунута вылетит последней, а последняя засунутая -- первой. Команды для работы со стеком следующие:
push -- положить в стек
pop -- вытащить из стека

Как пример, возьмем кусок кода программы:
blah-blah ; какие-то действия
mov ax, 21 ; в регистр ax число 21
push ax ; значение регистра ax в стек
mov ah, 09h ; какие то оперции, в которых замешан регистр ax
blah-blah
pop ax ; вытащить из стека


В результате, в регистре ax будет число 21. Думаю и со стеком разобрались. Повторяю, я не углубляюсь в каждую из тем, я просто хочу дать первый толчок людям, которые начали изучать ассемблер.

X Команды перехода

Ну а как же без них. Хех. Благодаря командам перехода, на ассемблере мы можем программировать типовые управляющие структуры, if-else и так далее. Но для этого надо познакомится с командой cmp. Те, кто учил си, должны знать, что в си есть функция strcmp, которая сравнивает строки. Подобная команда есть и в асме.
CMP (сокращенно от compare) команда, которая сравнивает два значение. Синтаксис у неё следующий:
cmp операнд1,операнд2
Следующим этапом, чтобы понятькоманды перехода, надо понять, что такое метки. Метки, в языке ассемблера, используются, чтоб сделать программу более понятной, ну и чтобы можно было, при определенных условиях, на них переходить. Метка объявляется следующим образом:
Имя_метки:
Т.е. пишем название метки, и двоеточие. Такс, с метками тоже разобрались, ну это не сложно, но метки очень полезны.
И наконец команды перехода. Их можно разделить на две группы: команды безусловного перехода и команды условного перехода.
Команды безусловного перехода. Единственная команда безусловного перехода, которую мы рассмотрим -- jmp. Все мы знаем слово "jump", т.е. прыжок, вот сокращение этого слова, jmp, и есть команда безусловного перехода. Не, ну всё логично, прыгнуть на определенную метку. Так, что-то я отвлекся, продолжим. Синтаксис у этой команды такой:
jmp метка
Думаю тут ничего сложного нет.
Команды условного перехода. То есть те команды перехода, которые выполняются по определенному условию. Вспомним начало этого раздела, команда cmp, в основном, команды условного перехода выполняются после этой команды. Я приведу небольшой список этих команд:

je / jne прыгнуть, если равны / если не равны
jg / jng / jge прыгнуть, если больше / если не больше / если больше или равны
jl / jnl / jle прыгнуть, если меньше / если не меньше / если меньше или равны
ja / jna / jae прыгнуть, если выше (в смысле больше) / если не выше (в смысле больше) / если выше (в смысле больше) или равны
jb / jnb / jbe прыгнуть, если ниже (в смысле меньше) / если не ниже (в смысле меньше) / если ниже (в смысле меньше) или равны

Вначале каждой команды стоит буква j, означающая jump, прыгнуть. Далее идет условие (чтобы понять почему именно так, надо вспомнить некоторые английские слова: equal, not, above, below, greater, less, перевод найдите в словаре).

Лучше посмотреть на примере. Я не буду писать целую программу. только небольшой её кусочек.

mov ax,22
mov bx,21
cmp ax,bx
je Equal
jg Greater
jl Less

Equal:
; вывести сообщение, что равны
Greater:
; вывести сообщение, что операнд 1 больше оперенда 2
Less:
; вывести сообщение, что операнд 1 меньше оперенда 2


На этом, про команды перехода хватит.

XI Циклы
Думаю не стоит объяснять, что такое циклы, поэтому сразу перейдем к делу. Для того, чтобы организовать цикл на ассемблере, есть два пути (может есть и больше, но мы их рассматривать не будем). Первый способ: в этом способе нам придется использовать команду условного перехода jcxz, переход будет выполнен только если в регистре cx будет 0. Давайте я приведу пример кода.

; blah-blah ; объявляем какие то данные
mov cx, 10 ; кидаем в регистр cx число, сколько будет тиков в цикле
m1: ; первая метка
dec cx ; вы еще не знакомы с этой командой, но она очень проста, декремент регистра cx, подобная команда есть inc -- инкремент

mov dx, offset msg ;
mov ah, 09h ; выводим какое-то сообщение
int 21h ;

jcxz exit ; если регистр cx равен нулю, переходим на метку exit
jmp m1 ; иначе переходим на метку m1
exit: ; метка exit
mov ah, 04ch ; выход из программы
int 21h


Как вы видите, всё просто, помещаем в регистр cx сколько раз должен повторится цикл, уменьшаем cx на один, выполняем действия, проверяем равен ли cx нулю, если да -- переходим на метку exit, если нет -- повторяем.

Второй способ: второй способ не требует использования команды перехода, во втором способе используется команда loop. Эта команда переводит нас на указанную метку пока cx не равен нулю. Давайте перепишем раннее написаный кусок кода, использовав команду loop.

; blah-blah ; объявляем какие то данные
mov cl, 10 ; кидаем в регистр cx (cl) число, сколько будет тиков в цикле
m1: ; первая метка
mov dx, offset msg ;
mov ah, 09h ; выводим какое-то сообщение
int 21h ;

loop m1 ; повторить m1, если cx не равен нулю
exit: ; метка exit
mov ah, 04ch ; выход из программы
int 21h


Вот и разобрались с циклами.

XII Процедуры

Мы уже "много" чего умеем, не так ли?) Но Вы не заметили, что некоторые участки кода повторяются? Конечно же заметили, для того, чтобы сделать код более читабельным и понятным придумали некие процедуры. Думаю вы уже догадались, что это такое, и объяснять это не стоит. Простая процедура объявляется следующим образом:

[I]имя_процедуры PROC
какие-то_действия
ret
имя_процедуры ENDP[I]

Как вы видите, ничего сложного нет. Например мы знаем, что для того, чтобы вывести текст на экран, надо в регистр ah поместить 09h, и вызвать прерывание 21 (int 21). Давайте объеденим это в процедуру. Получится что-то такое:

Write PROC
mov ah, 09h
int 21h
ret
Write ENDP


Используйте процедуры, чтобы сделать код понятнее.

XIII Include

В прошлом разделе мы познакомились с вами с процедурами. Благодаря процедурам можно сделать код понятнее. Так же есть директива include, которая позволяет нам включать куски кода из одного файла в другой. Уловили мысль? Мы напишем нужные процедуры, поместим их в отдельный файл, и просто его проинклудим. Таким образом код станет еще проще. Синтаксис у этой команды такой:

include файл.asm

Ничего сложно. В следующем шаге, мы напишем программу, используя эту директиву, поэтому в этом разделе я не буду приводить пример.

XIV Написание программы, используя полученные знания

Сейчас я приведу вам код программы, используя все знания, которые Вы получили (ну по крайней мере, могли бы получить). Сама программка будет очень глупой, и мы будем делать много лишних действий, но так надо, чтобы использовать все полученные знания =)
После кода программы, я построчно приведу объяснение. В самом коде я не буду оставлять комментариев (слегка геморойно мне сейчас это делать), а после программы всё объясню. Итак, код:

Код:
; ach.asm
MODEL SMALL
STACK 256
DATASEG
	bye db 'The end!) $'
	msg1 db 'CX < 5 || $'
	msg2 db 'CX > 5 || $'
	msg3 db 'CX = 5 || $'
CODESEG
start:	
	mov ax, @data
	mov ds, ax

	mov dx, offset bye
	mov cx, 5
	push dx
	push cx

	jmp begin
	include achadd.asm
begin:
	mov cx, 7
	cmp cx, 5
	je m3
	jg m2
	jl m1
m3:
	mov dx, offset msg3
	call write
	jmp preexit1
m2:
	mov dx, offset msg2
	call write
	jmp preexit1
m1:
	mov dx, offset msg1
	call write
preexit1:
	pop cx
	pop dx
preexit2:
	call write
	loop preexit2
ext:
	call exit
end start
;#############################
Код:
;achadd.asm
write proc

mov ah,09h
int 21h
ret

write endp
;+++++++++++++++++++++++++;
exit proc

mov ah, 1h
int 21h
mov ah, 04ch
int 21h
ret

exit endp
Тут у нас два файла, в первом главный код, во втором две процедуры.
Начнем с первого файла:
1 строка -- объявляем модель памяти
2 строка -- объявляем размер стека
3 строка -- начало сегмента данных
4-7 строки -- создаем переменные с сообщениями
8 строка -- начало сегмента кода
9 строка -- входим в "главную часть"
10-11 строки -- связываем данные с их сегментным регистром
13 строка -- записываем в регистр cx адрес переменной bye
14 строка -- в регистр cx помещаем 5
15 строка -- помещаем регистр dx в стек
16 строка -- помещаем регистр cx в стек
18 строка -- перепрыгиваем на метку begin
19 строка -- инклудим файл achadd.asm
20 строка -- объявляем метку begin
21 строка -- записываем в регистр cx число 7
22 строка -- сравниваем то, что в регистре сч с числом 5
23 строка -- если равные переходим на метку m3
24 строка -- если cx больше 5, переходим на метку m2
25 строка -- если cx меньше 5, переходим на метку m1
26 строка -- объявляем метку m3
27 строка -- записываем в dx адрес переменной msg3
28 строка -- вызываем процедуру write
29 строка -- прыгаем на метку preexit1
30-36 строки -- объявляем метки, записываем определенные сообщения и вызываем процедуру write (долго расписывать)
37 строка -- объявляем метку preexit1
38 строка -- вытаскиваем значение со стека в регистр cx
39 строка -- вытаскиваем значение со стека в регистр dx
40 строка -- объявляем метку preexit2
41 строка -- вызываем процедуру write
42 строка -- повторям, пока cx не станет равен нулю
43 строка -- объявляем метку ext
44 строка -- вызываем процедуру exit
45 строка -- end start

Второй файл, разберите сами, это будет как маленькое д.з.)) там ничего сложного нет.

XV Вывод

Ну, вот и всё) в этой статье я хотел показать, что ассемблер не такой уж и сложный язык (пока Вы не начнете учить что-то по-серьезнее, хе-хе). И хоть мы рассмотрели только основы, они будут очень полезны всем, кто хочет кодить не только на делфи)

Ну и ссылка на тасм, http://letitbit.net/download/5627.a5de7462230205a7a148f13dd/1065_tasm.rar.html
Рекомендую для прочтения книгу В.И. Юрова, Assembler 2-е издание.

Удачи в изучении ассемблера)
Vollkorn вне форума   Ответить с цитированием
Старый 24.03.2011, 15:38   #2
Vollkorn
 
Регистрация: 24.03.2011
Сообщений: 16
Репутация: 5
По умолчанию

Первоначально статья писалась для Античата, так что примеры написаны под Античат. Так как это глупо исправлять примеры, я этого делать не стал.
Vollkorn вне форума   Ответить с цитированием
Старый 24.03.2011, 21:06   #3
Vollkorn
 
Регистрация: 24.03.2011
Сообщений: 16
Репутация: 5
По умолчанию

Tigger, я же сказал, что TASM -- это просто удобная штука. И люди, которые всё это освоят, смогут легко понять принципы работы и в масме, и в фасме.
Vollkorn вне форума   Ответить с цитированием
Старый 25.03.2011, 08:38   #4
saper
 
Аватар для saper
 
Регистрация: 13.03.2011
Сообщений: 26
Репутация: 1
По умолчанию

Главное не TASM или MASM ... главное про саму архитектуру в картце расказать, кстати советую книгу "Голубь Н.Г Ассемблер..." там много полезных примеров и вещей, никогда не понимал ассемблер так как после ее книги
__________________
Тяжёлое детство: восьмибитные игрушки :secret:
saper вне форума   Ответить с цитированием
Старый 25.03.2011, 18:15   #5
Vollkorn
 
Регистрация: 24.03.2011
Сообщений: 16
Репутация: 5
По умолчанию

saper, не спорю, что в книге всё хорошо написано, но смысл этой статьи показать, что ассемблер -- это круто) и, так сказать, подтолкнуть начинающих к изучению этого языка.
Vollkorn вне форума   Ответить с цитированием
Ответ

Метки
ассемблер, для новичков, программирование

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход



Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Перевод: zCarot