Директива ASSUME с использованием masm - PullRequest
2 голосов
/ 25 мая 2019

Я пытался написать ассемблерный код с использованием ASSUME, но продолжаю получать ошибки, которые я не смог выяснить их причины. Вот пара примеров: Пример 1

.286
.model medium, c
pproc typedef ptr proc
.data
dummy db ?
.code
assume bx:ptr pproc
call [bx]
end

при сборке ошибки не возникает.

Если я изменяю .286 на .386, я получаю следующую ошибку:
Error A2158: type is wrong size for register.
Эта ошибка возникает для строки: Assume bx:ptr proc

Почему это происходит? Что нужно изменить в предположении, чтобы исправить ошибку?

Примечание: я заметил, что pproc определяется ассемблером как указатель FAR. ПОЧЕМУ?


пример 2:

.286
.model medium
.data
dummy db ?
.code
assume bx:near ptr 
call [bx]
call near ptr [bx[
end

Теперь, если я просто изменяю .286 на .386, я получаю следующую ошибку ассемблера:
assume bx:near ptr
A2158: Type is wrong size for register

Почему я получаю эту ошибку? Это ближний сегмент. Обратите внимание на инструкцию, которая делает то же самое без Assume.


пример 3

.286
.model medium, c
.data
dummy db ?
.code
assume bx:ptr byte
mov [bx],12h
mov byte ptr [bx],12h
end

Теперь, если я просто изменяю .286 на .386, я получаю следующие ошибки, когда попытка собрать его

для строки: assume bx:ptr byte Я получаю ошибку
A2158: Type is wrong size for register
Почему это происходит? Что нужно изменить в предположении, чтобы исправить ошибку?

для строки: mov [bx],12h
возникает следующая ошибка: error 2070 :invalid instruction operands.

Почему я получаю эту ошибку? Это ошибка? Это должно работать, я пытаюсь хранить 12h в [bx]. Обратите внимание на инструкцию, которая делает то же самое без Assume.

Ответы [ 5 ]

3 голосов
/ 25 мая 2019

Документация MASM 6.1 является хорошим ресурсом для написания сегментированного кода в реальном режиме (модели не-FLAT). Страница 43-47 содержит хорошую информацию о ASSUME и размерах сегментов. То, с чем вы сталкиваетесь, является побочным эффектом довольно тонкого способа, которым ASSUME будет действовать в зависимости от , где вы помещаете директиву .386 относительно директивы .MODEL. Это тонкое поведение описано в разделе Настройка размеров слова сегмента (только 80386/486) :

Настройка размеров слова сегмента (только 80386/486)

Тип использования в директиве SEGMENT указывает размер слова сегмента на процессорах 80386/486. Размер слова сегмента определяет значение по умолчанию размер операнда и адреса всех элементов в сегменте. Атрибут размера может быть USE16, USE32 или FLAT. Если вы укажете .386 или .486 перед директивой .MODEL, по умолчанию используется USE32. это Атрибут указывает, что элементы в сегменте обращаются с 32-разрядное смещение, а не 16-разрядное. Если .MODEL предшествует .386 или .486, по умолчанию используется USE16. Чтобы сделать USE32 значением по умолчанию, положить .386 или .486 перед .MODEL. Вы можете переопределить USE32 по умолчанию с атрибутом USE16 или наоборот.

Вы должны быть осторожны с тем, куда вы помещаете .386. Вы поместили его до .model, поэтому ассемблер предполагает, что по умолчанию все секции USE32. Похоже, вы пишете код, который будет работать в 16-битном реальном режиме (возможно, с использованием 386 инструкций и регистров), поэтому я считаю, что вы захотите убедиться, что USE16 является значением по умолчанию при использовании директив .code и .data. Чтобы получить желаемое поведение, я думаю, вы могли бы подумать об изменении:

.386
.model medium, c

Кому:

.model medium, c
.386

И понаблюдайте, что происходит.


Это вторая проблема, которую, я полагаю, вы испытываете. В MASM 5.1 добавлена ​​ дополнительная информация , которая может пролить свет на вашу проблему с FAR PTR и NEAR PTR. Он гласит:

Оператор PTR

Оператор PTR может использоваться для указания размера косвенного операнда регистра для инструкции CALL или JMP . Однако размер нельзя указать с помощью NEAR или FAR. Вместо этого используйте WORD или DWORD. (В 80386 32-битных сегментах используйте DWORD или FWORD.) Примеры показаны ниже:

      ; 8086, 80826, or 80386 16-bit mode

      jmp  WORD PTR [bx]        ; Legal near jump
      call NEAR PTR [bx]        ; Illegal near call
      call DWORD PTR [bx]       ; Legal far call
      jmp  FAR PTR [bx]         ; Illegal far jump

      ; 80386 32-bit mode only

      jmp  DWORD PTR [bx]       ; Legal near jump
      call NEAR PTR [bx]        ; Illegal near call
      call FWORD PTR [bx]       ; Legal far call
      jmp  FAR PTR [bx]         ; Illegal far jump

Это ограничение распространяется только на регистр косвенных операндов. РЯДОМ или FAR может применяться к операндам, связанным с метками. Примеры показано ниже:

      jmp  NEAR PTR pointer[bx] ; Legal
      call FAR PTR location     ; Legal

В разделе USE32, если вы хотите выполнить косвенный FAR JMP / CALL, используйте:

pproc typedef ptr fword

Если вы хотите сделать почти косвенный вызов в секции USE32, сделайте:

pproc typedef ptr dword

В разделе USE16, если вы хотите сделать косвенный FAR JMP / CALL, используйте:

pproc typedef ptr dword

Если вы хотите сделать почти косвенный вызов в секции USE16, сделайте:

pproc typedef ptr word
2 голосов
/ 25 мая 2019

Во всех примерах вы говорите MASM считать bx указателем на что-то 1 (сначала процедура, чем что-либо рядом, чем байт), и во всех случаях эти указатели находятся рядом (чтоподразумевается, если не указано иное).

Если вы укажете .286 MASM создает сегмент данных по умолчанию, который предполагается адресуемым 16-разрядным, аналогично сегменту кода по умолчанию (размер операнда / размера адреса по умолчанию 16-разрядный).
Если вы используете .386, то создаются 32-битные версии.

Ближайшие указатели на 16-разрядный сегмент данных являются 16-разрядными, а ближние указатели на 32-разрядные сегменты данных - 32-разрядные.
Регистр bx всегда является 16-разрядным.
Так что .386 с ASSUME BX: PTR <SOMETHING> не может работать.


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

0 голосов
/ 06 июня 2019

Майкл:

Вот пример кода, который создает 16-битный код:

.Model small,c ;since cpu instruction is after .Model it causes USE16 to be used
.286
.code
assume bx:word
call bx
end

Поскольку use16 действует, это создает 16-битный сегмент, а .286 указывает ему использовать 16-битные инструкции. Когда приведенный выше код собран, он создает коды операций FF D3 для инструкции Call bx. Инструкции «вызов NEAR PTR bx» или «вызов NEAR16 PTR bx» также создают такие же коды операций.

Вот еще один пример кода, который создает 32-битный код:

.Model small,c ;since cpu instruction is after .Model it causes USE16 to be used
.386
.code
assume ebx:dword
call ebx
end

Поскольку use16 действует, это создает 16-битный сегмент, а .386 говорит ему использовать 32-битные инструкции. Когда приведенный выше код собран, он создает коды операций 66 FF D3 для инструкции Call ebx. Инструкции «вызов NEAR PTR ebx» или «вызов NEAR32 PTR ebx» или «вызов FAR16 ptr ebx» также создают такие же коды операций. Ассемблер распознает, что 386 инструкций используются в 16-битном сегменте, что заставляет ассемблер вставлять перед каждая инструкция 386 а 66 в гексе. Обратите внимание, что оба кода операции для 16-битного и 32-битного кода одинаковы, с той лишь разницей, что там находится префиксный код операции. Если был создан 32-битный сегмент и используется 16-битная инструкция, то тот же 66 в шестнадцатеричном коде префикса ставится перед 16-битными кодами операций. Обратите внимание, что префиксный байт находится там или нет, есть единственная разница. Код операции с префиксом (66) помещается туда только тогда, когда размер использования сегмента (use16 или use32) не соответствует размеру инструкции процессора (16-битный или 32-битный). Правила должны быть одинаковыми для ASSUME, использующего 16-битные или 32-битные регистры, но их нет в MASM.

0 голосов
/ 03 июня 2019

После обширного тестирования я обнаружил «правила» для оператора ASSUME в следующем формате: регистр ASUME: размер PTR

Разрешенные настройки для "ASSUME reg: PTR {Size}

Cases where cpu instruction is BEFORE .MODEL or no cpu instruction before .MODEL:

                             |user supplied |  condition
                             |   values     |
                             |  reg  | size |
.286 instruction or less is  |8-bit  | BYTE |can only use BYTE, no PTR     |
before tiny,small or medium  |16-bit | WORD |if <WORD or >WORD requires PTR|
.MODEL or no cpu instruction 
before tiny,small or medium
.MODEL. Causes internal use16. 

                             |user supplied |  condition
                             |   values     |
                             |  reg  | size |
.286 instruction or less is  |8-bit  | BYTE |can only use BYTE, no PTR     |
before compact,large,or huge |16-bit | WORD |can only use WORD, no PTR     |
.MODEL or no cpu instruction 
before compact,large or huge
.MODEL. Causes internal use16. 

                               |user supplied |  condition
                               |   values     |
                               |  reg  | size |
.386 instruction or greater is |8-bit  | BYTE |can only use BYTE, no PTR       |
before tiny,small or medium    |16-bit | WORD |can only use WORD, no PTR       |
.MODEL. Causes internal use32. |32-bit |DWORD |if <DWORD or >DWORD requires PTR|

                               |user supplied |  condition
                               |   values     |
                               |  reg  | size |
.386 instruction or greater is |8-bit  | BYTE |can only use BYTE, no PTR       |
before compact,large,or huge   |16-bit | WORD |can only use WORD, no PTR       |
.MODEL. Causes internal use32. |32-bit |DWORD |if <DWORD or >DWORD requires PTR|

Cases where cpu instruction is AFTER .MODEL 

                               |user supplied |  condition
                               |   values     |
                               |  reg  | size |
.286 instruction or less is    |8-bit  | BYTE |can only use BYTE, no PTR     |
after tiny,small or medium     |16-bit | WORD |if <WORD or >WORD requires PTR|
.MODEL. Causes internal use16. 

                               |user supplied |  condition
                               |   values     |
                               |  reg  | size |
.286 instruction or less is    |8-bit  | BYTE |can only use BYTE, no PTR     |
after compact,large,or huge    |16-bit | WORD |can only use WORD, no PTR     |
.MODEL. Causes internal use16.

                               |user supplied |  condition
                               |   values     |
                               |  reg  | size |
.386 instruction or greater is |8-bit  | BYTE |can only use BYTE, no PTR     |
after tiny,small or medium     |16-bit | WORD |if <WORD or >WORD requires PTR|
.MODEL. Causes internal use16. |32-bit |DWORD |can only use DWORD, no PTR    |

                               |user supplied |  condition  
                               |   values     |
                               |  reg  | size |
.386 instruction or greater is |8-bit  | BYTE |can only use BYTE, no PTR       |
after compact,large,or huge    |16-bit | WORD |can only use WORD, no PTR       |
.MODEL. Causes internal use16. |32-bit |DWORD |if <DWORD or >DWORD requires PTR|

THIS IS THE WAY IT SHOULD BE:

                               |user supplied |  condition
                               |   values     |
                               |  reg  | size |
.286 instruction or less is    |8-bit  | BYTE |can only use BYTE, no PTR     |
before any .MODEL instruction  |16-bit | WORD |if <WORD or >WORD requires PTR|
or no cpu instruction before
.MODEL. Causes internal use16.

                               |user supplied |  condition
                               |   values     |
                               |  reg  | size |
.386 instruction or greater is |8-bit  | BYTE |can only use BYTE, no PTR       |
before any .MODEL instruction. |16-bit | WORD |if <WORD or >WORD requires PTR  |
Causes internal use32.         |32-bit |DWORD |if <DWORD or >DWORD requires PTR|


                               |user supplied |  condition
                               |   values     |
                               |  reg  | size |
.286 instruction or less is    |8-bit  | BYTE |can only use BYTE, no PTR     |
after any .MODEL instruction   |16-bit | WORD |if <WORD or >WORD requires PTR|
Causes internal use16.

                               |user supplied |  condition
                               |   values     |
                               |  reg  | size |
.386 instruction or greater is |8-bit  | BYTE |can only use BYTE, no PTR       |
after any .MODEL instruction.  |16-bit | WORD |if <WORD or >WORD requires PTR  |
Causes internal use16.         |32-bit |DWORD |if <DWORD or >DWORD requires PTR|
0 голосов
/ 25 мая 2019

Какова цель Директивы MASM Assume является отличным обобщением использования директивы ASSUME. В былые времена было также обычным делом видеть, что он используется для определения списка регистров сегментов. Такое использование в значительной степени устарело на современных процессорах.

...