Model small ассемблер что это
Перейти к содержимому

Model small ассемблер что это

  • автор:

What is meaning of .model small in 8086 programs?

I am a beginner in 8086 assembly language. I can understand the logic used in the program and write small programs myself. But I just want to know what this does:

What is explanation for .model small?

I am using masm .

Sakil Mallick's user avatar

2 Answers 2

With .model tiny you get a program where CS , DS , and SS are all pointing to the same 64KB of memory. The stack is placed in the highest region of this 64KB segment.

With .model small you get a program where CS points to a segment of its own, followed by the segment where DS and SS are pointing to. The stack is placed in the highest region of the SS segment.

The directive .stack 300h is telling MASM the size of the stack, so MASM can warn you when the rest of the program (data,bss,heap) would clash with the stack.

In both these models all access to data items is done using near pointers.

Sep Roland's user avatar

Because of 8086 being a 16-bit architecture, it has difficulties in accessing more than 64 KB memory.

The most efficient way to use pointers is to use the dedicated 16-bit registers (like bx ). However, when your program wants to access more than 64 KB, it has to use also segment registers (like es ). To allow both ways of addressing, memory models were invented.

So, the directive .model small tells the assembler that you intend to use the small memory model — one code segment, one data segment and one stack segment — and the values of the segment registers are never changed.

It has the following effects:

You are allowed to write the instruction retn (return from a near subroutine) as ret . Because the assembler knows that all your code is in the same segment, all your subroutines will be near (i.e. have a 16-bit address), and all ret instructions mean retn .

Sounds silly and insignificant? Read on.

If your code is scattered across several source files, you will have call instructions that call subroutines that the assembler doesn’t know anything about. When you use a small memory model, it knows at least that each subroutine has a 16-bit address, and a near call opcode can be used.

You could write code without declaring your memory model, but then you’d have to call near instead of just call .

If all your source files declare .model small , the linker will take all the code segments and try to fit them all into 64 KB (the same for data segments). This may fail, if the stuff is too big.

Small assembly programs usually don’t care about memory model — 64 KB code is more than enough to write complex programs, unless you’re using a big external library. In such case, .model small can mean "I don’t care about that memory model stuff, just use the default".

Что означает .model small в программах 8086?

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

Какое объяснение для .model small?

Я использую masm .

2 ответа

С .model tiny вы получаете программу, в которой CS , DS и SS все указывают на одни и те же 64 КБ памяти. Стек размещается в самой высокой области этого сегмента размером 64 КБ.

С помощью .model small вы получаете программу, в которой CS указывает на собственный сегмент, за которым следует сегмент, на который указывают DS и SS . Стек помещается в самую верхнюю часть сегмента SS .

Директива .stack 300h сообщает MASM размер стека, поэтому MASM может предупредить вас, когда остальная часть программы (данные, bss, куча) столкнется со стеком.

В обеих этих моделях весь доступ к элементам данных осуществляется с помощью ближайших указателей.

Поскольку 8086 является 16-разрядной архитектурой, у него возникают трудности с доступом к более чем 64 КБ памяти.

Самый эффективный способ использования указателей — использовать выделенные 16-битные регистры (например, bx ). Однако, когда ваша программа хочет получить доступ к более чем 64 КБ, она также должна использовать регистры сегментов (например, es ). Чтобы разрешить оба способа адресации, были изобретены модели памяти.

Итак, директива .model small сообщает ассемблеру, что вы собираетесь использовать малую модель памяти — один сегмент кода, один сегмент данных и один сегмент стека — и значения регистров сегментов никогда не меняются.

Он имеет следующие эффекты:

Вам разрешено писать инструкцию retn (возврат из подпрограммы near ) как ret . Поскольку ассемблер знает, что весь ваш код находится в одном сегменте, все ваши подпрограммы будут иметь формат near (т.е. иметь 16-битный адрес), а все инструкции ret означают retn .

Звучит глупо и незначительно? Читай дальше.

Если ваш код разбросан по нескольким исходным файлам, у вас будут инструкции call , которые вызывают подпрограммы, о которых ассемблер ничего не знает. Когда вы используете небольшую модель памяти, она знает, по крайней мере, что каждая подпрограмма имеет 16-битный адрес, и можно использовать код операции вызова near .

Вы можете написать код, не объявляя свою модель памяти, но тогда вам придется call near вместо просто call .

Если все ваши исходные файлы объявляют .model small , компоновщик возьмет все сегменты кода и попытается уместить их все в 64 КБ (то же самое для сегментов данных). Это может потерпеть неудачу, если материал слишком большой.

Небольшие программы на ассемблере обычно не заботятся о модели памяти — кода размером 64 КБ более чем достаточно для написания сложных программ, если вы не используете большую внешнюю библиотеку. В таком случае .model small может означать «Меня не волнует эта модель памяти, просто используйте значение по умолчанию».

Модели памяти и упрощенные директивы определения сегментов

SMALL – код размещается в одном сегменте, а данные и стек – в другом (для их описания могут применяться разные сегменты, но объединенные в одну группу). Эту модель памяти также удобно использовать для создания программ на ассемблере;

COMPACT – код размещается в одном сегменте, а для хранения данных могут использоваться несколько сегментов, так что для обращения к данным требуется указывать сегмент и смещение (данные дальнего типа);

MEDIUM – код размещается в нескольких сегментах, а все данные – в одном, поэтому для доступа к данным используется только смещение, а вызовы подпрограмм применяют команды дальнего вызова процедуры;

LARGE и HUGE – и код, и данные могут занимать несколько сегментов;

FLAT – то же, что и TINY, но используются 32-битные сегменты, так что максимальный размер сегмента, содержащего и данные, и код, и стек, – 4 Мб.

Язык – необязательный операнд, принимающий значения C, PASCAL, BASIC, FORTRAN, SYSCALL и STDCALL. Если он указан, подразумевается, что процедуры рассчитаны на вызов из программ на соответствующем языке высокого уровня, следовательно, если указан язык C, все имена ассемблерных процедур, объявленных как PUBLIC, будут изменены так, чтобы начинаться с символа подчеркивания, как это принято в C.

Модификатор – необязательный операнд, принимающий значения NEARSTACK (по умолчанию) или FARSTACK. Во втором случае сегмент стека не будет объединяться в одну группу с сегментами данных.

После того как модель памяти установлена, вступают в силу упрощенные директивы определения сегментов, объединяющие действия директив SEGMENT и ASSUME. Кроме того, сегменты, объявленные упрощенными директивами, не требуется закрывать директивой ENDS – они закрываются автоматически, как только ассемблер обнаруживает новую директиву определения сегмента или конец программы.

Директива .CODE описывает основной сегмент кода

_TEXT segment word public ’CODE’

для моделей TINY, SMALL и COMPACT и

name_TEXT segment word public ’CODE’

для моделей MEDIUM, HUGE и LARGE (name – имя модуля, в котором описан данный сегмент). В этих моделях директива .CODE также допускает необязательный операнд – имя определяемого сегмента, но все сегменты кода, описанные так в одном и том же модуле, объединяются в один сегмент с именем NAME_TEXT.

Директива .STACK описывает сегмент стека и эквивалентна директиве

STACK segment para public ’stack’

Необязательный параметр указывает размер стека. По умолчанию он равен 1 Кб.

Описывает обычный сегмент данных и соответствует директиве

_DATA segment word public ’DATA’

Описывает сегмент неинициализированных данных:

_BSS segment word public ’BSS’

Этот сегмент обычно не включается в программу, а располагается за концом памяти, так что все описанные в нём переменные на момент загрузки программы имеют неопределённые значения.

Описывает сегмент неизменяемых данных:

CONST segment word public ’CONST’

В некоторых операционных системах этот сегмент будет загружен так, что попытка записи в него может привести к ошибке.

Сегмент дальних данных:

имя_сегмента segment para private ’FAR_DATA’

Доступ к данным, описанным в этом сегменте, потребует загрузки сегментного регистра. Если не указан операнд, в качестве имени сегмента используется FAR_DATA.

Сегмент дальних неинициализированных данных:

имя_сегмента segment para private ’FAR_BSS’

Как и в случае с FARDATA, доступ к данным из этого сегмента потребует загрузки сегментного регистра. Если имя сегмента не указано, используется FAR_BSS.

Во всех моделях памяти сегменты, представленные директивами .DATA, .DATA?, .CONST, .FARDATA и .FARDATA?, а также сегмент, описанный директивой .STACK, если не был указан модификатор FARSTACK, и сегмент .CODE в модели TINY автоматически объединяются в группу с именем FLAT – для модели памяти FLAT или DGROUP – для всех остальных моделей. При этом сегментный регистр DS (и SS, если не было FARSTACK, и CS в модели TINY) настраивается на всю эту группу, как если бы была выполнена команда ASSUME.

Model small ассемблер что это

Не удивлю наверно не кого, дав понятие переменной — это место в памяти которое имеет имя и тип. Создавая программу на ассемблере нам нужно будет определять наши данные. Данные обычно определяются в сегменте данных. TASM поддерживает ряд директив которые помогут нам выделить именованное место под переменные.

Пока хватит, тем более что мы в ближайшее время будет работать с типом данных db. Итак, давайте попробуем определить байт в нашей программе.

А теперь собираем и смотрим в отладчике. Выполните первый команды инициализации регистра данных .

Все в норме по смещению 0 от регистра данных находится наша переменная с содержимым 31h, что в таблице ASCII соответствует цифре 1. Так же эту переменную можно помещать в регистр вот так например:

И опять в отладчик смотреть.

Видите, все поместилось и команда MOV теперь имеет другой вид, в квадратных скобочках адрес откуда берется переменная. Можно и обратную операцию провести поместить из регистра в переменную:

В отладчике Вы увидите, что теперь в переменной код 32, что соответствует числу 2:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *