2014-11-30 2 views
0

У меня есть ошибка в одном из моих циклов, и я не могу это исправить. Это часть моего задания для школы. У меня есть массив с 20 элементами, и мне нужно умножить каждый элемент на 2, используя сдвиг бит. Это вроде работает, но каждый раз, когда у меня есть перенос, он добавляет 2 к предыдущему элементу массива, а не к одному. Я не могу правильно переносить перенос через массив. Это мой первый семестр со сборкой, поэтому я ценю вашу помощь. Кроме того, пожалуйста, держите его простым, если можете. Спасибо.Ошибка умножения массива языка сборки с использованием сдвига бит

Это то, что я хочу: 0000000009 ==> 0000000018 0000000099 ==> 0000000198

Это то, что я получаю. 0000000009 ==> 0000000028 0000000099 ==> 00000002108

Вот код.

ARR1 \t DB 20 DUP (0) 
 

 
MULTIPLYING PROC 
 
\t MOV AX, 0 
 
\t MOV CX, 19 
 
\t .WHILE CX != 0 
 
\t \t \t \t MOV DI, CX 
 
\t \t \t \t MOV AL, [DIGIT_ARR1+DI] 
 
\t \t \t \t ;MOV BL, 2 
 
\t \t \t \t ;MUL BL 
 
\t \t \t \t SHL AX, 1 
 
\t \t \t \t .IF AX > 9 \t \t ; IF THE NEW DIGIT IS LARGER THAN 9 
 
\t \t \t \t \t SUB AX, 10 
 
\t \t \t \t \t MOV AH, 0 
 
\t \t \t \t \t MOV [DIGIT_ARR1+DI], AL 
 
\t \t \t \t \t DEC DI 
 
\t \t \t \t \t ADD [DIGIT_ARR1+DI], 1 
 
\t \t \t \t .ELSEIF 
 
\t \t \t \t \t MOV [DIGIT_ARR1+DI], AL \t ; IF IT IS LESS THAN 9, THEN JUST INSERT IT BACK INTO THE ARRAY 
 
\t \t \t \t .ENDIF 
 
\t \t DEC CX 
 
\t .ENDW \t 
 
\t RET 
 
MULTIPLYING ENDP

+0

Пожалуйста, вы можете указать процессор или набор инструкций. Сборка использует двоичные регистры, и похоже, что ваш код манипулирует каким-то типом массива denary. – Phil

+0

А я вижу, вы используете массив адресов для представления каждой цифры. – Phil

+0

Да, я забыл сказать, что мне нужно иметь одну цифру за раз, потому что программа работает с BCD. Я использую набор команд 8085 16 бит. – Jake

ответ

1

Итак, оказалось, что Фил был прав. Я переписывал свои данные. Трюк состоял в том, чтобы прочитать значение, выполнить умножение с помощью сдвига бит, добавить перенос (если есть) и только затем записать обратно в массив. Таким образом, я могу умножить каждый элемент на два и не испортить свои данные.

ПРИМЕЧАНИЕ ДЛЯ НАЧИННИКОВ, КАК МОЖНО: бит сдвига будет умножаться только на два, поэтому, если вам нужно умножить что-то еще, используйте mul или imul. Кроме того, сдвиг бит вправо будет делить на два. Цикл ниже умножит BCD в массиве на два. Отдел работает одинаково, только убедитесь, что вы обрабатываете массив другим способом и добавляете 10 к каждой следующей цифре, когда у вас есть перенос. Вы также должны будете убедиться, что вы не добавите перенос, как только достигнете конца массива. Язык ассемблера не проверяет, не вышли ли за пределы массива.

MULTIPLYING PROC 
 
\t PUSH CX 
 
\t PUSH AX 
 
\t MOV CARRY, 0    ; START WITH EMPTY CARRY FLAG 
 
\t MOV CX, 19     ; ARRAY SIZE 
 
\t .WHILE CX > 0 
 
\t \t MOV DI, CX    ; GET ELEMENT ADDRESS 
 
\t \t MOV AL, [ARR1+DI] \t \t ; READ THE ELEMENT 
 
\t \t SHL AL, 1    ; DOUBLING THE DIGIT 
 
\t \t ADD AL, CARRY   ; ADD THE CARRY FLAG 
 
\t \t MOV CARRY, 0   ; CLEAR THE CARRY FLAG 
 
\t \t .IF AL > 9 \t \t   ; IF THE NEW DIGIT IS LARGER THAN 9 
 
\t \t \t SUB AL, 10 
 
\t \t \t MOV CARRY, 1 \t  ; SET CARRY FLAG 
 
\t \t \t MOV [ARR1+DI], AL \t ; INSERTING THE DOUBLED DIGIT BACK TO THE ARRAY 
 
\t \t .ELSEIF 
 
\t \t \t MOV [DIGIT_ARR1+DI], AL \t ; IF IT IS LESS THAN 9, INSERT IT BACK INTO THE ARRAY 
 
\t \t \t MOV CARRY, 0 
 
\t \t .ENDIF 
 
\t \t DEC CX 
 
\t .ENDW \t ; END OF MULTIPLICATION PROC 
 
\t POP AX 
 
\t POP CX 
 
\t RET 
 
MULTIPLYING ENDP

0

Я думаю, что проблема в том, что вы пишете обратно в тот же массив адресов, которые вы читаете с. Когда вы носите, это развращает расчет.

например. От: 99

Positon 19 = 9 
9*2 = 18 (set position 19 to 8, increment position 18 to 10) 
Position 18 = 10 
10*2 = 20 (set position 18 to 10, increment position 17 to 1) 
Position 17 = 1 
1*2 = 2 (set position 17 to 2) 
Result: 2108 

Но вам все еще нужно больше работать, потому что даже с пустыми адресами назначения вы получаете

Positon 19 = 9 
9*2 = 18 (set position 19 to 8, increment position 18 to 1) 
Position 18 = 9 
9*2 = 18 (set position 18 to 8, increment position 17 to 1) 
Position 17 = 1 
1*2 = 2 (set position 17 to 2) 
Result: 288 

Вам нужно добавить 8 к 1 в положении 18, так что вы получите 9 . И вы не делаете третьего умножения, потому что позиция 17 пуста в массиве адресов источника. Я надеюсь в этом есть смысл.

Вы не должны получать ошибки переполнения цифр при умножении на 2, как это, но вам может потребоваться обработать его при умножении на большие числа.

+0

Ну, мне нужно написать тот же массив, что и я, потому что мне может понадобиться умножить число в этом массиве на 2 раза, пока программа не будет выполнена. Я использую этот цикл и несколько подобных для вычисления большого числа. Но поскольку мы можем использовать только 16 бит, и конечный результат огромен, мы должны использовать BCD. Есть ли лучший способ умножить каждую цифру в массиве на 2? – Jake

+0

Возможно, если вы сначала смещаете все адреса и выполняете 2-й цикл для обработки переполнения. 99 -> 1818 -> 198 – Phil

Смежные вопросы