Просто для цикла и суммы
Я пытаюсь выучить язык ассемблера HCS12, но примеров в интернете недостаточно. Я пытался написать код, но безуспешно. Я застрял. Это не совсем домашнее задание. Может кто-нибудь написать это на ассемблере HCS12 с комментариями? Я хочу код, потому что действительно хочу читать его шаг за шагом. Кстати, есть ли другой способ определить массив?
;The array arr will be located at $1500 and the contents {2, 5, 6, 16, 100, 29, 60}
sum = 0;
for i = 0 : 6
x = arr[i];
if( x < 50 )
sum = sum + x
end
Моя попытка:
Entry:
;2,5,6,16,100,39,60
LDAA #2
STAA $1500
LDAA #5
STAA $1501
LDAA #6
STAA $1502
LDAA #16
STAA $1503
LDAA #100
STAA $1504
LDAA #39
STAA $1505
LDAA #60
STAA $1506
CLRA ; 0 in accumulator A
CLRB ; 0 in accumulator B
ADDB COUNT ; B accumulator has 6
loop:
;LDAA 1, X+ ; 1500 should be x because it should increase up to 0 from 6
; A accumulator has 2 now
BLO 50; number less than 50
;ADDA
DECB
BNE loop
1 ответ
Ниже приведен один из возможных способов реализации вашего конкретного цикла FOR.
Это в основном для HC11, который на уровне источника совместим с HCS12, поэтому он также должен правильно собираться для HCS12. Однако HCS12 имеет некоторые дополнительные инструкции и режимы адресации (например, индексированное автоинкремент), которые могут сделать код немного короче и даже более читабельным. Во всяком случае, я на самом деле не пробовал это, но все должно быть в порядке.
Кстати, ваш код показывает, что у вас есть некоторое фундаментальное непонимание определенных инструкций. Например, BLO 50
не означает ветвление, если аккумулятор ниже 50. Это означает проверку соответствующих флагов CCR (регистр кода состояния), которые должны быть уже установлены какой-либо предыдущей инструкцией, и переход к адресу 50 (очевидно, не то, что вы предполагали), если значение меньше чем цель. Чтобы сравнить регистр со значением или некоторым местом в памяти, вы должны использовать CMPx
инструкции (например, CMPA
).
;The array arr will be located at $1500 and the contents {2, 5, 6, 16, 100, 29, 60}
org $1500 ;(somewhere in ROM)
arr fcb 2,5,6,16,100,29,60 ;as bytes (use dw if words)
org $100 ;wherever your RAM is
;sum = 0;
sum rmb 2 ;16-bit sum
org $8000 ;wherever you ROM is
;for i = 0 : 6
clrb ;B is your loop counter (i)
stb sum ;initialize sum to zero (MSB)
stb sum+1 ; -//- (LSB)
ForLoop cmpb #6 ;compare against terminating value
bhi ForEnd ;if above, exit FOR loop
; x = arr[i];
ldx #arr ;register X now points to array
abx ;add offset to array element (byte size assumed)
ldaa ,x ;A is your target variable (x)
;;;;;;;;;;;;;;;;;;; ldaa b,x ;HCS12 only version (for the above two HC11-compatible lines)
inx ;X points to next value for next iteration
;;;;;;;;;;;;;;;;;;; ldaa 1,x+ ;HCS12 only version (for the above two HC11-compatible lines)
; if( x < 50 )
cmpa #50
bhs EndIf
; sum = sum + x
adda sum+1
staa sum+1
ldaa sum
adca #0
staa sum
EndIf
incb ;(implied i = i + 1 at end of loop)
bra ForLoop
;end
ForEnd
Выше предполагается, что ваш массив является постоянным, поэтому он находится где-то в ПЗУ во время сборки. Если ваш массив динамический, он должен находиться в оперативной памяти, и вам нужно будет использовать код для его загрузки (аналогично тому, как вы это делали). Однако для эффективности обычно используется цикл при загрузке (копировании) нескольких значений из одного места в другое. Это и более читабельно, и более эффективно с точки зрения необходимой памяти кода.
Надеюсь это поможет.
Отредактировано: забыл инициализировать SUM
в ноль.
Отредактировано: в отличие от HC08, CLRA
в HC11 очищает Carry, поэтому последовательность CLRA
, ADCA
неправильно. Заменено на правильное: LDAA
, ADCA #0