Документация 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