Каково назначение команды ORG в Assembler?
В мс дос при запуске com файла первые 100H байт перед запущенным кодом резервируется под разного рода управляющие структуры. Потому вся адресация внутри кода должна начинаться с смещением 100H байт.
Директива org 100H как раз и говорит компилятору что всю адресацию внутри кода нужно сместить именно на эти 100H байт.
т.е. например у тебя в коде есть область где ты собираешься что то хранить которую ты обьявляешь например
data1 DB 30h
которую внутри кода ты адресуешь как
mov ax,OFFSET Data1
при компиляции структура OFFSET Data1 преобразовывается в конкретный адрес к которому прибавиться значение из org
How does assembler process "org 100h" directive?
I know, what this directive is do. As I know program-loader doesn’t see this directive, so, how assembler process it?
3 Answers 3
It sets the current address during assembly to be 100h. That’s all it is. A simple assignment.
The directive does not control where in the result image the following instructions will be placed, but rather where the instructions would be placed after being loaded into memory.
«org <100h>» instructs the compiler with the to-be runtime information to evaluate addresses, as binary image will be loaded with offset (and first 100h bytes possibly to be used for PSP etc. in your context)
This comes in hand to access any data in the same segment (usually when DS=CS, especially true for com files when «you know nothing except your CS»), or when doing a JMP to absolute offset in rare cases.
In other words, it makes all further labels in a segment to account from the specific offset: just that.
Переменные
Переменные хранятся в памяти по определенным адресам. Программисту проще иметь дело именами переменных, чем с адресами в памяти. Например, переменная с именем «var1» будет более понятна в коде программы, чем адрес 5A73:235B, особенно когда количество переменных велико.
Наш компилятор поддерживает два типа переменных: BYTE и WORD.
имя DB значение
имя DW значение
DB — Define Byte — определяет байт.
DW — Define Word — определяет слово.
имя — может быть любой комбинацией букв или цифр, но должно начинаться с буквы. Можно объявлять безымянные переменные, которые имеют адрес, но не имеют имени.
Как вы уже знаете из части 2 этих уроков, команда MOV используется для копирования значения из источника в приемник.
Давайте посмотрим другой пример с командой MOV:
Скопируйте вышеприведенный код в редактор кода Emu8086 и нажмите клавишу F5, чтобы откомпилировать и загрузить этот код в эмулятор. Вы увидите примерно такую картину:
На рисунке вы можете заметить команды, похожие на те, что используются в нашем примере. Только переменные заменены фактическими местоположениями в памяти. Когда компилятор создает машинный код, он автоматически заменяет имена всех переменных их смещениями. По умолчанию сегмент загружен в регистр DS (в COM-файлах значение регистра DS устанавливается таким же, что и значение в регистре CS — сегменте кода).
В таблице памяти (memory) первый столбец — это смещение, второй столбец — это шестнадцатиричное значение, третий столбец — десятичное значение, а последний столбец — это символ ASCII, соответствующий данному числу.
Компилятор не чувствителен к регистру, поэтому «VAR1» и «var1» — это одно и то же.
Смещение переменной VAR1 — это 0108h, а полный адрес — 0B56:0108.
Смещение переменной var2 — это 0109h, а полный адрес — 0B56:0109. Эта переменная имеет тип WORD, поэтому занимает 2 БАЙТА. Принято младший байт записывать по меньшему адресу, поэтому 34h размещается перед 12h.
Вы можете увидеть некоторые другие инструкции после команды RET. Это случается потому, что дизассемблер не знает, где начинаются данные. Он только обрабатывает значения в памяти и понимает их как имеющие силу инструкции процессора 8086 (мы изучим их позже).
Вы можете даже написать программу, используя только директиву DB:
Скопируйте вышеприведенный код в редактор кода Emu8086 и нажмите клавишу F5, чтобы откомпилировать и загрузить этот код в эмулятор. Вы получите тот же самый дизассемблированный код и тот же самый результат работы программы!
Как вы можете догадаться, компилятор только преобразует исходный код программы в набор байтов. Этот набор байтов называется машинным кодом. Процессор обрабатывает машинный код и выполняет его.
ORG 100h — это директива компилятора (она указывает компилятору как обрабатывать исходный код). Эта директива очень важна при работе с переменными. Она указывает компилятору, какой исполняемый файл будет загружаться в смещение (offset) 100h (256 байтов), так что компилятор должен вычислить правильный адрес для всех переменных, когда он размещает имена переменных с их смещениями. Директивы никогда не преобразуются в какой-либо реальный машинный код. Почему исполняемый файл загружается по смещению 100h? Операционная система хранит некоторые данные о программе в первых 256 байтах, начиная от CS (сегмента кода), такие как параметры командной строки и т.д. Все это справедливо только для COM-файлов, файлы EXE загружаются по смещению 0000, и обычно используют специальный сегмент для переменных. Может быть, мы поговорим об EXE-файлах позже.
Массив можно рассматривать как цепочку переменных. Текстовая строка — это пример массива байтов, в котором каждый символ представлен значением ASCII-кода (0..255).
Вот некоторые примеры определения массивов:
a DB 48h, 65h, 6Ch, 6Ch, 6Fh, 00h
b DB ‘Hello’, 0
b — это точная копия массива a — когда компилятор видит строку, заключенную в кавычки, он автоматически преобразует ее в набор байтов. Эта таблица показывает участок памяти, где эти массивы объявлены:
Вы можете получить значение любого элемента массива, используя квадратные скобки, например:
Вы можете также использовать какой-либо из регистров BX, SI, DI, BP, например:
MOV SI, 3
MOV AL, a[SI]
Если необходимо объявить большой массив, вы можете использовать оператор DUP.
Синтаксис для DUP:
количество DUP ( значение(я) )
количество — количество дубликатов (любая константа).
значение — выражение, которое будет дублироваться оператором DUP.
а это альтернативный способ объявления:
еще один пример:
а это альтернативный способ объявления:
d DB 1, 2, 1, 2, 1, 2, 1, 2, 1, 2
Конечно, вы можете использовать DW вместо DB, если требуется хранить числа более 255, или менее -128. DW не может быть использован для объявления строк!
Оператор DUP не может содержать более 1020 знаков в качестве операнда! (в последнем примере 13 знаков). Если вам необходимо объявить очень большой массив, разделите его на две строки (вы получите один большой массив в памяти).
Получение адреса переменной
Есть такая команда LEA (Load Effective Address) и альтернативный оператор OFFSET. Как OFFSET так и LEA могут быть использованы для получения смещения адреса переменной.
LEA более мощная, т.к. она также позволяет вам получить адрес индексированных переменных. Получение адреса переменной может быть очень полезно в различных ситуациях, например, если вам необходимо поместить параметр в процедуру.
Напоминание:
Чтобы указать компилятору тип данных, вы должны использовать следующие префиксы:
BYTE PTR — для байта.
WORD PTR — для слова (два байта).
Например:
Emu8086 поддерживает короткие префиксы:
b. — для BYTE PTR
w. — для WORD PTR
иногда компилятор может вычислить тип данных автоматически, но вы не можете и не должны полагаться на это, если один из операндов является непосредственным значением.
Здесь первый пример:
Здесь другой пример, который использует OFFSET вместо LEA:
Оба примера функционально идентичны.
LEA BX, VAR1
MOV BX, OFFSET VAR1
даже компилируются в одинаковый машинный код: MOV BX, num
num — это 16-битовое значение смещения переменной.
Пожалуйста учтите, что только эти регистры могут использоваться внутри квадратных скобок (как указатели памяти):
BX, SI, DI, BP!
(См. предыдущую часть уроков).
Константы подобны переменным, но они существуют до того, как ваша программа откомпилирована (ассемблирована). После определения константы ее значение не может быть изменено. Для определения константы используется директива EQU:
Этот пример функционально идентичен коду:
MOV AX, 5 |
Вы можете наблюдать переменные во время выполнения программы, если выберите пункт «Variables» в меню «View» эмулятора.
Чтобы наблюдать массивы, вы должны щелкнуть по переменной и установить свойство Elements — размер массива. В Ассемблере нет строгих типов данных, поэтому любые переменные могут быть представлены как массив.
- HEX — шестнадцатиричная (основа 16).
- BIN — двоичная (основа 2).
- OCT — восмеричная (основа 8).
- SIGNED — десятичная со знаком (основа 10).
- UNSIGNED — десятичная без знака (основа 10).
- CHAR — коды ASCII-символов (всего 256 символов, некоторые символы невидимы).
Можно вводить числа в любой системе, шестнадцатиричные цифры должны иметь суффикс «h«, двоичные — суффикс «b«, восмеричные — суффикс «o«, десятичные цифры не требуют суффикса. Строка может быть введена следующим способом:
‘hello world’, 0
(эта строка заканчивается нулем).
Массив может быть введен следующим способом:
(массив может быть массивом байтов или слов, это зависит от того, выбран ли BYTE или WORD для введенной переменной).
whats .org 100h?
can i ask something whats the used of .org 100h in assembly language.
and why it is 100h why can/t it be 60,70,80 or 90h?
- 10 Contributors
- 15 Replies
- 23K Views
- 7 Years Discussion Span
- Latest Post 5 Years Ago Latest Post by Reverend Jim
Recommended Answers
I assume you mean for a PC based 80×86 processor running DOS?
Actual firmware uses a reset vector for code startup.
Lookup a *.com file.
ORG (abbr. for ORiGin) is an assembly directive (not an instruction). It defines where the machine code (translated assembly program) is to place in memory. As for ORG 100H this deals with 80×86 COM program format (COMMAND) which consist of only one segment of max. 64k bytes. 100H says that …
- It doesn’t produce any output.
- Please don’t revive old threads.
you even didn’t know how many quations i shared in that JPEG file
@ Abottonion : By «quations», do you mean questions? Where is you JPEG file?
All 15 Replies
I assume you mean for a PC based 80×86 processor running DOS?
Actual firmware uses a reset vector for code startup.
Lookup a *.com file.
ORG (abbr. for ORiGin) is an assembly directive (not an instruction). It defines where the machine code (translated assembly program) is to place in memory. As for ORG 100H this deals with 80×86 COM program format (COMMAND) which consist of only one segment of max. 64k bytes. 100H says that the machine code starts from address (offset) 100h in this segment, effective address is CS:100H. For com format the offset is always 100H. I suppose that addresses 0 to 100H could be used by bios, but I am not that sure. Another example is ORG 7C00H for intel exe program format.
So, Simple answer.
We usually write [org 100h] because windows loads every .com software at offset 100h. So we have to include org 100h at start of program if we write org 60h or 80h or etc. then our all calls to our functions will jmp at wrong address..
for example I write a program:
Now look at these lines when windows loaded this program then this was at:
Org 100h, Jmp strat V db 0,1,2,3,4 Strat: Mov cl,5 Mov al, 0 Mov si, 0 Next: Add al, v[bx] Inc bx Dec cl Cmp cl, o Jnz next ret i need output of above script code,,
Back in the days of MS-DOS, when a program was loaded into memory a structure called a «program segment prefix» was always prepended to it, and that structure was 100h bytes long. Therefore the actual code began at 100h, and the directive «org 100h» instructs the assembler to assemble code with 100h as the starting address.
The orogram segment prefix contained all sorts of stuff, some of it documented, some not. The most useful item to be found in it was the command line typed in by the user at offset 80h.
.EXE program files had a header which told the operating system where the first line of code would be in the loaded program, but .COM files did not. For that reason, .EXE programs didn’t need the org 100h.