matB[DI][BX]
- это не двумерная индексация, а просто matB[DI + BX]
. Я не знаю, почему emu8086 поддерживает этот запутанный синтаксис, но я бы не рекомендовал его.
Машинный код
8086 поддерживает только простое добавление в режимах адресации, поэтому вам нужно что-то вроде add DI, N
для перемещения по вектору столбца.
Под decM
: мне пришлось переместить значение BP в BX, потому что эмулятор вычисляет неправильное смещение.
Странно. Сначала я задавался вопросом, было ли у вас правильное смещение, но неправильная база сегмента (потому что BP подразумевает SS, а BX подразумевает DS), но .model small
дает вам DS = SS .
Но я думаю, что вам нужно инициализировать DS самостоятельно. Если я правильно понимаю, DOS .exe
начинается с DS base = start of PSP. Почему MS-DOS не инициализирует регистры DS и ES? .
Таким образом, у вас, вероятно, правильное смещение, но неправильная база сегмента, что приводит к неправильному линейному адресу. Если BP
работает, то это не смещение, которое неправильно в режиме адресации seg:off
.
Как только вы исправите это, вы сможете отлаживать свой код с помощью отладчика. Сегменты могут сбивать с толку, но остальные должны быть легко отлажены с помощью одного шага и поиска любых неожиданных инструкций в руководстве.
[BP+BX]
не является допустимым режимом адресации, так что да, вам нужно MOV SI,BP
до ADD matC[BX][SI],AX
. Или add bx,bp
или что-то еще, если вы можете заглушить регистр.
Вы можете просто увеличить 3 указателя (место назначения, источник столбца и источник строки) с inc
или add reg,N
/ sub reg,P-1
или чем угодно, вместо того, чтобы пытаться сохранить i
, j
и k
индексы в регистрах и масштабирование их перед каждым 2D-доступом.
Несбалансированный push / pop
Ваш внутренний цикл имеет 2 нажатия и 2 щелчка. Но ваши внешние 2 петли (decN
и decP
) имеют 2 толчка и 1 щелчок. Это кажется обреченным на неудачу, и переполнит стек с большим N.
Я не пытался точно определить, какое значение должно куда идти, и если вы пытаетесь всегда вывести значение обратно в регистр, из которого оно получено, или если вы используете сохранение / восстановление как возможность вставить его в другой регистр. В вашем коде нет комментариев ...
Использование всех регистров вместо памяти - это хорошо, но вам нужно использовать немного памяти. Возможно, вам будет легче (и более эффективный код), если вы используете BP в качестве указателя кадра, поэтому у вас есть произвольный доступ к стеку. Ограничение себя нажимать / выдвигать для сохранения / восстановления означает, что вы должны сохранять / восстанавливать во внутреннем цикле, а не просто сохранять некоторые элементы внешнего цикла в памяти.
Вы можете сохранить счетчик циклов в памяти, например dec byte [BP-2]
/ jnz decP
, вместо сохранения / восстановления CX, чтобы использовать его в качестве счетчика циклов для всех 3 циклов.
Или с указателями в регистрах, вы можете проверить их вместо того, чтобы тратить отдельный регистр или ячейку памяти в качестве счетчика цикла. Нравится
top_of_loop:
...
; bottom of a loop
cmp DI, OFFSET matC + N*P * 2
jb top_of_loop
; fall through when DI has
; or OFFSET matC + SIZEOF matC, or put a label at the end of matC
Тогда у вас есть CX, доступный как временный (например, для накопления точечного продукта строки / столбца, который станет элементом матрицы результатов с add cx, ax
), или для удержания границы цикла, если вы хотите поддерживать переменную времени выполнения размеры матрицы.
Вам также не нужно использовать DX таким, какой вы есть. imul byte ptr matB[DI][BX]
будет работать без необходимости отдельной загрузки в регистр. (Или imul byte ptr [BX]
с указателем.) Это освобождает вас от DX.