Сборка 8086 - определение конфликтует с прямой ссылкой
Я сузил свою проблему до 4 строк кода.
MOV BX, testz
ADD AL, [testz]
INT 20h
testz:
~ ^
#ERROR 16: Definition Conflicts With Forward Reference @@@@#
db ?
Что вы думаете не так с этим кодом? Я перемещаю сам адрес в регистр BX и добавляю байтовое значение в тестовом адресе к AL.
В более крупной программе я также получаю #ERROR 13: комбинация байтов и слов не разрешена.
Но метка - это слово, где [метка] - это байт. Почему мой компилятор не может их различить?
ADD BL, [second]
MOV BX, second
~ ^
#ERROR 13: Byte/Word Combination Not Allowed
second:
~ ^
#ERROR 16: Definition Conflicts With Forward Reference @@@@#
db ?
Потому что я не вижу конфликта между байтами и словами.
Благодарю.
Обновление: это был, я полагаю, немного длинный комментарий, поэтому я редактирую свой вопрос
Мой компилятор интерпретирует смещение testz и testz одинаково. Я посмотрел на байт-коды и не увидел никакой разницы.
MOV BX, testz ADD AL, [BX]
Приведенный выше код работает, но есть ли другой способ сделать это в одной строке, например
ДОБАВИТЬ AL, [testz]
Всякий раз, когда я помещаю имя метки в [], это просто не приемлемо в соответствии с моим компилятором a86. Но я чувствую, что они разрешены на языке.
2 ответа
Я подозреваю, что вы хотите MOV BX, offset testz
, Похоже, что ваш ассемблер интерпретирует [testz]
а также testz
означать то же самое.
Вы можете подтвердить это, попробовав вместо этого условно эквивалентный LEA BX, testz
РЕДАКТИРОВАТЬ: (из http://www.csn.ul.ie/~darkstar/assembler/manual/a14.txt):
ERROR 16: Definition Conflicts With Forward Reference
This error occurs when the assembler has previously guessed
the type of a forward-referenced symbol in order to determine
what kind of instruction to generate, and the guess turned out
to be wrong. The error is reported at the time the symbol is
defined. For example, when A86 sees MOV AX,FOO, it will
assume FOO is an immediate value. This error is reported if
FOO turns out to be a word variable: FOO DW 0. You need to
search backwards from the error message, to references of FOO,
and specify the type you intend to be used: MOV AX,FOO W. If
you really did intend to load the offset of FOO and not the
memory contents, you can code MOV AX,OFFSET FOO to make the
error message go away.
Проблема, с которой вы столкнулись, связана с тем, что A86 - это однопроходный ассемблер. Когда вы используете такие символы, какtestz
а также second
перед их определением A86 должен угадать, что это такое. Предполагается, что это будут немедленные значения, но позже обнаруживается, что они на самом деле являются ярлыками. Многоэтапный ассемблер может вернуться и изменить ранее принятое решение, но A86 этого не делает. Он просто выдает ошибку (#16). Вот почему ошибка появляется в исходном файле рядом с определением: именно там был A86, когда обнаружил проблему.
Вы можете использовать директивы offset
, d
, w
и так далее, чтобы явно указать A86, что вы хотите, чтобы ему не приходилось гадать.
В руководстве A86 объясняется:"ВАЖНО: вы должны понимать различие между меткой и переменной, потому что вы можете сгенерировать другую инструкцию, чем предполагали, если перепутаете их. Например, если вы объявляете XXX: DW?, Двоеточие после XXX означает, что XXX является метка; инструкция MOV SI,XXX перемещает непосредственный постоянный адрес XXX в регистр SI. С другой стороны, если вы объявляете XXX DW? без двоеточия, тогда XXX - это словесная переменная; та же инструкция MOV SI,XXX теперь делает что-то другое: загружает значение времени выполнения слова памяти XXX в регистр SI. Вы можете переопределить определение символа при любом использовании с помощью оператора немедленного значения OFFSET или операторов переменных памяти B,W,D,Q или T. Таким образом, MOV SI,OFFSET XXX загружает непосредственное значение, указывающее на XXX, независимо от того, как XXX был объявлен; MOV SI,XXX W загружает слово-переменную в XXX независимо от того, как XXX был объявлен ".
Это должно ответить на ваш второй вопрос: когда A86 видит add bl, [second]
это предполагает, что second
будет непосредственным операндом размером в байты, поскольку bl
регистр размером в байт.
Ваша следующая строка mov bx, second
ожидает second
чтобы быть операндом размером в слово, но A86 уже отметила, что second
будет байтом, поэтому вы получите ошибку №13.
Вместо этого вы можете получить то, что хотите:
add bl, second b ; add the byte at memory location ds:second to bl
mov bx, offset second
Как правило, эти проблемы исчезнут, если вы определите свои символы перед их использованием. Например, это будет работать:
name example1 ; good code
code segment
org 0100h
main: ; - MACHINE CODE
mov bx, main ; BB0001 - put 0100h in bx
mov bx, offset main ; BB0001 - put 0100h in bx
; ^ offset directive not needed here
; A86 already knows what to do
mov bx, [main] ; 8B1E0001 - put 00BBh in bx
; ^ brackets work fine to dereference main here
mov bx, main w ; 8B1E0001 - put 00BBh in bx
; ^ w does the same thing as brackets
org 0150h
goodbye:
int 020h
code ends
end main
но это не сработает:
name example2 ; will not assemble
code segment
org 0100h
main: ; - MACHINE CODE
mov bx, goodbye ; BB5001 - put 0150h in bx
; ^ A86 assumes goodbye is an immediate value. This assumption
; turns out to be a good one, so this line works OK
mov bx, offset goodbye; BB5001 - put 0150h in bx
; ^ offset directive tells A86 that goodbye will be an immediate
; value. You can skip it, since A86 assumes that anyway
mov bx, [goodbye] ; this line is the culprit!
; ^ A86 doesn't know what to do about these brackets
mov bx, goodbye w ; 8B1E5001 - put 20CDh (`int 020h`) in bx
; ^ w directive tells A86 that goodbye will be a word
; variable
org 0150h
goodbye: ; label goodbye not defined until way down here!
int 020h
code ends
end main
Руководство по DOS указывает указатель для обработчика для таких:
мув топор, слово ptr es:[bx],BBBB
где BBBB является базой
также ссылка на базу для сегмента - то же самое после нажатия cx[я думаю, я не могу вспомнить]
на что то же самое, что и выше, за исключением BBBB SSSS для сегментирования
Теперь я написал обработчик, когда моя мышь остановила функцию из-за неудачного сбоя, и я использовал это слово ptr как байт вместо слова, и оно работает, так как я никогда не делал реальный указатель слова, а просто использовал слово ptr программа вместе с обратным двоичным преобразованием байта в шестнадцатеричный код [A6 назад - 65].
Кроме того, я обнаружил ошибку в DOS, которая была вызвана вызовом INT [не так, как в сборке отладки или сборке программы, вызвав int ##, но фактически сделав прямой вызов 8080, и фактом этого является то, что это не так. вызов прерывания, но вызов IRQ. Код инструкции неверен, особенно в презентации. Также на Intel es:[bx] не работает - нужно использовать es[bx]
Кроме того, если у меня в голове - xtension ---- чтобы ответить на ваш вопрос, вы ссылаетесь на 8-битный регистр, а затем на 16-битный регистр, которому вы указываете ADD bl, а затем измените bx после операнда add. ваша ошибка № 13.
То, что вы должны сделать, это убедиться, что bl совместим с BX до или, таким образом, вы не получите прямой ошибки ссылки, к которой, в сущности, это и относится. Инструкция ADD автоматически защищает BX от амнипуляции до тех пор, пока запрос вычисления или запрос команды не будет полностью завершено, если только оно не выполнено как запрос IRQ, к которому он может быть приостановлен с помощью sti и cli, между которыми находится ссылка для изменения таблицы страниц или ссылочной таблицы.