Сборка 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, между которыми находится ссылка для изменения таблицы страниц или ссылочной таблицы.

Другие вопросы по тегам