М. ИванюшинУчимся программировать
В одном из предыдущих разделов были опубликованы коды нескольких полезных программ. Но команды, при помощи которых написаны эти программы, оказались скрыты для вас. Здесь мы попробуем показать вам "кухню программирования" и рассмотрим программы сложения, вычитания, умножения, деления, преобразования шестнадцатеричных чисел в десятичные и преобразования десятичных в шестнадцатеричные. ;СЛОЖЕНИЕ ТРЕХБАЙТНЫХ ЧИСЕЛ ;вход в программу: ;первое слагаемое SL0, SL1, SL2; ;второе слагаемое SL3, SL4, SL5; ;результат работы: ;сумма SL3, SL4, SL5;SUMMA3: LHLD SLO XCHG ;D,E - младшие ;байты первого ;слагаемого LHLD SL3 ;H,L - младшие ;байты второго ;слагаемого DAD D ;H,L - сумма этих ;младших байтов. ;Если при сложении ;возникнет перенос, ;он будет в даль- ;нейшем учтен в ;команде ADC M SHLD SL3 ;сохранили в памяти ;первые два ;байта результата LDA SL2 ;в регистре А ;старший байт ;первого слагаемого LXI H,SL5 ;H,L - адрес ;старшего байта ;второго слагаемого ADC M ;сложение старших ;байтов слагаемых. ;Учтен перенос, ;если он был при ;сложении командой DAD MOV M,A ;результат в SL5 RET
Вычитание ;ВЫЧИТАНИЕ ДВУХБАЙТНЫХ ЧИСЕЛ ;вход в программу: ;H,L - уменьшаемое, ;D,E - вычитаемое, ;результат работы: ;В,С - разность.VICH2: MOV A,L ;ВЫЧИТАНИЕ МЛАДШИХ БАЙТОВ SUB E MOV С,А ;ВЫЧИТАНИЕ СТАРШИХ БАЙТОВ MOV А,Н SBB D ;учитывается перенос, ;если он был ;при обработке ;младших байтов MOV В,А RET Для вычисления разности трехбайтных чисел можно использовать следующую программу: ;ВЫЧИТАНИЕ ТРЕХБАЙТНЫХ ЧИСЕЛ ;вход в программу: ;уменьшаемое SL3,SL4,SL5, ;вычитаемое SL0,SL1,SL2, ;результат работы: ;разность SL3,SL4,SL5.VICH3: LXI H,SL0 ;HL - адрес млад- ;шего байта ;вычитаемого LXI D,SL3 ;DE - адрес млад- ;шего байта ;уменьшаемого LDAX D ;A - младший байт ;уменьшаемого SUB М STAX D ;вычислен и сохранен ;младший байт ;разности INX D ;DE - адрес байта SL4 INX H ;HL - адрес байта SL1 LDAX D SBB M STAX D ;в SL4 второй байт ;разности INX H INX D LDAX D SBB M STAX D ;в SL5 третий байт ;разности RET
Умножение ;УМНОЖЕНИЕ ;вход в программу: ;А - множитель, DE — множимое, ;результат работы: ;HL - произведениеUMNOG: LXI Н,0 ;сброшен промежу- ;точный результат ;****** шаг 3 ****** SHAG3: ORA А ;проверка оконча- ;ния работы RZ ;если содержимое ;регистра А ;равно нулю - ;умножение закончено ;****** шаг 1 ****** RAR ;младший бит мно- ;жителя в переносе INC SDVIG ;если перенос ;равен нулю - ;пропуск сложения DAD D ;сложение множи- ;мого и промежуточ- ;ного результата ;******шаг 2 ****** SDVIG: XCHG DAD H ;сдвиг множимого XCHG JMP SHAG3
В строке с меткой SHAG3 проверка на равенство нулю аккумулятора выполнена при помощи логической операции ИЛИ аккумулятора с самим собой. Эта операция не изменяет содержимое аккумулятора, но устанавливает все признаки. Можно было бы проверить содержимое аккумулятора на равенство нулю при помощи команды CPI 00, но эта команда занимает больше места в памяти и дольше выполняется. ;ДЕЛЕНИЕ ЧЕТЫРЕХБАЙТНОГО ЧИСЛА ;НА ЧЕТЫРЕХБАЙТНОЕ ;вход в программу: ;DE - адрес делимого, ;HL - адрес делителя, ;результат работы: ;RES —частное, ;DE — адрес остатка.DELEN: XRA А STA RES STA RES+1 STA RES+2 STA RES+3 ;сброшено значение ;частного ;ЗАПИСЬ ДЕЛИТЕЛЯ В ЯЧЕЙКУ DEL MOV A,M STA DEL INX H MOV A,M STA DEL+1 INX H MOV A,M STA DEL+2 INX H MOV A,M STA DEL+3 INX H MOV A,M STA DEL+4 LXI H,RES ;вычитание делимого из делителя Rl: LDA DEL MOV C,A LDA DEL+1 MOV B,A LDAX D SBB С STAX D INX D LDAX D SBB В STAX D INX D LDA DEL+2 MOV C,A LDA DEL+3 MOV B,A LDAX D SBB С STAX D INX D LDAX D SBB В STAX D DCX D DCX D DCX D ;восстановлено ;исходное значение ;регистров DE JC KD ;если перенос уста- ;новлен, значит ;делитель стал ;больше делимого PUSH PSW ;запомнено состояние ;переноса ;подсчет числа вычитаний ;делителя из делимого ;HL - адрес результата DELI: INR M JNZ R3 INX H ;если установлен ;признак равенства ;нулю, значит, в ;результате выполнения ; команды INR M ;возник перенос и ;его надо учесть INR М ;увеличен на единицу ;следующий байт ;результата JNZ R2 INX H INR M DCX H ;восстановление ;исходного значения R2: DCX H ;регистров HL R3: POP PSW ;восстановлен ;текущий перенос ;для правильного ;выполнения сложения ;в цикле R1 JMP R1 ;ВОССТАНОВЛЕНИЕ ОСТАТКА KD: LDA DEL MOV C,A LDA DEL+1 MOV B,A LDAX D ADD С STAX D INX D LDAX D ADC В STAX D INX D LDA DEL+2 MOV C,A LDA DEL+3 MOV B,A LDAX D ADC С STAX D INX D LDAX D ADC В STAX D DCX D DCX D DCX D ;DE - адрес остатка RET
Преобразование чисел двоичное число: бит7 * 27 + бит6 * 26 + бит5 * 25 + бит4 * 24 + + бит3 * 23 + бит2 * 22 + бит1 * 21 + бит0 * 20 преобразуется к виду: десятичное число: ((((((бит7 * 2 + бит6) * 2 + бит5) * 2 + бит4) * 2 + + бит3) * 2 + бит2) * 2 + бит1) * 2 + бит0. ;ПРЕОБРАЗОВАНИЕ ДВОИЧНОГО ЧИСЛА ;В ДВОИЧНО-ДЕСЯТИЧНОЕ ;BCD2B - программа перевода двухбайтного ;двоичного числа в двоично-десятичное. ;Двоичное число передается ;в регистрах HL, ;результат работы: ;А - десятки тысяч, ;В - тысячи и сотни, ;С - десятки и единицы. ;BCD1B - программа перевода однобайтного ;числа в двоично-десятичный код. ;Двоичное число записывается ;в регистр Н, регистр L сбрасывается. ;результат работы: ;А - разряды сотен, ;В - разряды десятков и единиц. BCD2B: MVI Е,17 ;установка счетчика ;первого цикла CALL CONV ;вычисление младшего ;двоично-десятичного байта MOV С,А ;вычисленный результат сохранен MVI Е,17 ;установка счетчика ;второго цикла JMP PROD BCD1B: MVI E,9 ;установка счетчика ;для программы BCD1B CALL CONV ;вычисление двух ;старших байтов MOV В,А ;запомнен промежуточный ;двоично-десятичный результат MOV A,L ;установка старшего ;двоично-десятичного байта RET CONV: XRA А ;сброс регистра А в нуль SBIT: DCR E ;уменьшение на 1 ;счетчика числа циклов RZ DAD H ;сдвиг старших разрядов ;в перенос ADC A DAA ;двоично-десятичная коррекция JNC SBIT ;двоично-десятичный ;байт больше 99? INX H ;да JMP SBIT
Обратите внимание, как в строке с меткой CONV: устанавливается в нуль регистр А. Операция ИСКЛЮЧАЮЩЕЕ ИЛИ аккумулятора с самим собой обнулит его, а также сбросит и бит переноса.
Заключение |