1. Вы находитесь в архивной версии форума xaker.name. Здесь собраны темы с 2007 по 2012 год, большинство инструкций и мануалов уже неактуальны.
    Скрыть объявление

Нужна помощь в объединении функций с программой

Тема в разделе "Assembler", создана пользователем ReaD, 7 янв 2009.

  1. ReaD

    ReaD Новичок

    Регистрация:
    16 апр 2008
    Сообщения:
    10
    Симпатии:
    0
    Баллы:
    0
    Собственно вопрос: Курсовой проект предполагает внедрение нескольких разработанных функций в тело программы в которой предусмотрено их выполнение. Функции являються отдельнымы файлами.

    Программа 1:
    Код:
    ; 	Проверка процедуры сложения длинных чисел - ввод слагаемых
    ;	с клавиатуры и вывод суммы на экран монитора.
            EXTRN _decnum:far, _decdig:far, _input:far, _outbuf:far 
    	EXTRN _lngdup:far, _lngadd:far
            DOSSEG
    	.MODEL SMALL
    	.STACK 400h
    	.DATA
    addend1	dd 30 dup (?) ; первое слагаемое
    addend2 dd 30 dup (?) ; второе слагаемое
    sum	dd 30 dup (?) ; сумма
    dupnum  dd 30 dup (?) ; копия числа
    prmpt1	db "Введите первое слагаемое", 0Dh, 0Ah, 24h
    prmpt2	db "Введите второе слагаемое", 0Dh, 0Ah, 24h
    prmpt3	db "Сумма:", 0Dh, 0Ah, 24h
    prmpt4  db "Повторить ? (Y)", 0Dh, 0Ah, 24h
    symbuf	db 257 dup (?)  ; текстовый буфер 
            .CODE
    	.486
    start:  mov  ax, @data	; ax = код сегмента данных
    	mov  ds, ax	; ds = ax
    redo:	lea  dx, prmpt1 ; адрес выводимого текста
    	mov  ah, 09	; код функции DOS
    	int  21h	; вывод текста на экран
    	lea  eax, symbuf; адрес текстового буфера 
    	push eax	; запись адреса в стек
    	call _input	; ввод числа с клавиатуры
    	add  esp, 4	; удаление параметров из стека
    	lea  eax, symbuf; адрес текстового буфера 
    	push eax	; запись адреса в стек
    	lea  eax, addend1; адрес первого слагаемого
    	push eax	; запись адреса в стек
    	call _decnum	; формирование длинного целого
    	add  esp, 8	; удаление параметров из стека
    	lea  dx, prmpt2 ; адрес выводимого текста
    	mov  ah, 09	; код функции DOS
    	int  21h	; вывод текста на экран
    	lea  eax, symbuf; адрес текстового буфера 
    	push eax	; запись адреса в стек
    	call _input	; ввод числа с клавиатуры
    	add  esp, 4	; удаление параметров из стека
    	lea  eax, symbuf; адрес текстового буфера 
    	push eax	; запись адреса в стек
    	lea  eax, addend2; адрес второго слагаемого
    	push eax	; запись адреса в стек
    	call _decnum	; формирование длинного целого
    	add  esp, 8	; удаление параметров из стека
    	lea  eax, addend1;адрес первого слагаемого
    	push eax	; запись адреса в стек
    	lea  eax, addend2;адрес второго слагаемого
    	push eax	; запись адреса в стек
    	lea  eax, sum	; адрес суммы
    	push eax	; запись адреса в стек
    	call _lngadd	; сложение длинных чисел
    	add  esp, 12	; удаление параметров из стека
    	lea  dx, prmpt3 ; адрес выводимого текста
    	mov  ah, 09	; код функции DOS
    	int  21h	; вывод текста на экран
    	lea  eax, sum	; адрес суммы
    	push eax	; запись адреса в стек
    	lea  eax, dupnum; адрес для дубликата
    	push eax	; запись адреса в стек
    	call _lngdup	; создание копии числа
    	add  esp, 8	; удаление параметров из стека
    	lea  eax, dupnum; адрес копии числа
    	push eax	; запись адреса в стек
    	lea  eax, symbuf; адрес текстового буфера
    	push eax	; запись адреса в стек
    	call _decdig	; преобразование в ASCII
    	add  esp, 8	; удаление параметров из стека
    	lea  eax, symbuf; адрес текстового буфера
    	push eax	; запись адреса в стек
    	call _outbuf	; вывод десятичного числа
    	add  esp, 4	; удаление параметров из стека
    ;	Вопрос оператору и ожидание его реакции
    	lea  dx, prmpt4 ; адрес выводимого текста
    	mov  ah, 09	; код функции DOS
    	int  21h	; вывод текста на экран
    GetChar:mov  ah, 1	; код функции "проверка готовности"
    	int  16h	; обращение к BIOS
    	jz   GetChar	; символ не введен
    	xor  ah, ah	; код функции "чтение символа в al"
    	int  16h	; обращение к BIOS
    	cmp  al, 'Y'	; введена буква Y ?
    	je   @F		; -> да
    	cmp  al, 'y'	; введена буква y ?
    	jne  eoprg	; -> нет, конец работы
    @@:	jmp  redo	; еще один повтор
    eoprg:  mov  ax, 4C00h  ; ax = код завеpшения задачи
    	int  21h	; возвpат в DOS
    ;
    	END  Start
    
    
    Программа 2:
    Код:
    ; 	Проверка процедуры умножения длинных чисел - ввод
    ;	сомножителей с клавиатуры и вывод произведения на
    ;	экран монитора.
            EXTRN _decnum:far, _decdig:far, _input:far, _outbuf:far 
    	EXTRN _lngdup:far, _lngmul:far
            DOSSEG
    	.MODEL SMALL
    	.STACK 400h
    	.DATA
    mltpl	dd 30 dup (?) ; множимое
    factor  dd 30 dup (?) ; множитель
    product dd 60 dup (?) ; произведение
    dupnum  dd 60 dup (?) ; копия числа
    prmpt1	db "Введите множимое", 0Dh, 0Ah, 24h
    prmpt2	db "Введите множитель", 0Dh, 0Ah, 24h
    prmpt3	db "Произведение:", 0Dh, 0Ah, 24h
    prmpt4  db "Повторить ? (Y)", 0Dh, 0Ah, 24h
    symbuf	db 1026 dup (?)  ; текстовый буфер 
            .CODE
    	.486
    start:  mov  ax, @data	; ax = код сегмента данных
    	mov  ds, ax	; ds = ax
    redo:	lea  dx, prmpt1 ; адрес выводимого текста
    	mov  ah, 09	; код функции DOS
    	int  21h	; вывод текста на экран
    	lea  eax, symbuf; адрес текстового буфера 
    	push eax	; запись адреса в стек
    	call _input	; ввод числа с клавиатуры
    	add  esp, 4	; удаление параметров из стека
    	lea  eax, symbuf; адрес текстового буфера 
    	push eax	; запись адреса в стек
    	lea  eax, mltpl	; адрес множимого
    	push eax	; запись адреса в стек
    	call _decnum	; формирование длинного целого
    	add  esp, 8	; удаление параметров из стека
    	lea  dx, prmpt2 ; адрес выводимого текста
    	mov  ah, 09	; код функции DOS
    	int  21h	; вывод текста на экран
    	lea  eax, symbuf; адрес текстового буфера 
    	push eax	; запись адреса в стек
    	call _input	; ввод числа с клавиатуры
    	add  esp, 4	; удаление параметров из стека
    	lea  eax, symbuf; адрес текстового буфера 
    	push eax	; запись адреса в стек
    	lea  eax, factor; адрес множителя
    	push eax	; запись адреса в стек
    	call _decnum	; формирование длинного целого
    	add  esp, 8	; удаление параметров из стека
    	lea  eax, mltpl	; адрес множимого
    	push eax	; запись адреса в стек
    	lea  eax, factor; адрес множителя
    	push eax	; запись адреса в стек
    	lea  eax, product;адрес произведения 
    	push eax	; запись адреса в стек
    	call _lngmul	; умножение длинных чисел
    	add  esp, 12	; удаление параметров из стека
    	lea  dx, prmpt3 ; адрес выводимого текста
    	mov  ah, 09	; код функции DOS
    	int  21h	; вывод текста на экран
    	lea  eax, product; адрес произведения
    	push eax	; запись адреса в стек
    	lea  eax, dupnum; адрес для дубликата
    	push eax	; запись адреса в стек
    	call _lngdup	; создание копии числа
    	add  esp, 8	; удаление параметров из стека
    	lea  eax, dupnum; адрес копии числа
    	push eax	; запись адреса в стек
    	lea  eax, symbuf; адрес текстового буфера
    	push eax	; запись адреса в стек
    	call _decdig	; преобразование в ASCII
    	add  esp, 8	; удаление параметров из стека
    	lea  eax, symbuf; адрес текстового буфера
    	push eax	; запись адреса в стек
    	call _outbuf	; вывод десятичного числа
    	add  esp, 4	; удаление параметров из стека
    ;	Вопрос оператору и ожидание его реакции
    	lea  dx, prmpt4 ; адрес выводимого текста
    	mov  ah, 09	; код функции DOS
    	int  21h	; вывод текста на экран
    GetChar:mov  ah, 1	; код функции "проверка готовности"
    	int  16h	; обращение к BIOS
    	jz   GetChar	; символ не введен
    	xor  ah, ah	; код функции "чтение символа в al"
    	int  16h	; обращение к BIOS
    	cmp  al, 'Y'	; введена буква Y ?
    	je   @F		; -> да
    	cmp  al, 'y'	; введена буква y ?
    	jne  eoprg	; -> нет, конец работы
    @@:	jmp  redo	; еще один повтор
    eoprg:  mov  ax, 4C00h  ; ax = код завеpшения задачи
    	int  21h	; возвpат в DOS
    ;
    	END  Start
    
    Программа 3:
    Код:
    ; 	Проверка процедуры вычитания длинных чисел - ввод чисел
    ;	с клавиатуры и вывод  разности на экран монитора. Числа 
    ;	разной длины перед вычитанием выравниваются.
            EXTRN _decnum:far, _decdig:far, _input:far, _outbuf:far 
    	EXTRN _lngdup:far, _lngsub:far, _lngext:far, _lnginv:far
            DOSSEG
    	.MODEL SMALL
    	.STACK 400h
    	.DATA
    decrem	dd 30 dup (?) ; уменьшаемое
    subtr	dd 30 dup (?) ; вычитаемое
    differ	dd 30 dup (?) ; разность
    dupnum  dd 30 dup (?) ; копия числа
    prmpt1	db "Введите уменьшаемое", 0Dh, 0Ah, 24h
    prmpt2	db "Введите вычитаемое", 0Dh, 0Ah, 24h
    prmpt3	db "Разность:", 0Dh, 0Ah, 24h
    prmpt4  db "Повторить ? (Y)", 0Dh, 0Ah, 24h
    prmpt5	db "-", 24h
    symbuf	db 257 dup (?)  ; текстовый буфер 
            .CODE
    	.486
    start:  mov  ax, @data	; ax = код сегмента данных
    	mov  ds, ax	; ds = ax
    redo:	lea  dx, prmpt1 ; адрес выводимого текста
    	mov  ah, 09	; код функции DOS
    	int  21h	; вывод текста на экран
    	lea  eax, symbuf; адрес текстового буфера 
    	push eax	; запись адреса в стек
    	call _input	; ввод числа с клавиатуры
    	add  esp, 4	; удаление параметров из стека
    	lea  eax, symbuf; адрес текстового буфера 
    	push eax	; запись адреса в стек
    	lea  eax, decrem; адрес уменьшаемого
    	push eax	; запись адреса в стек
    	call _decnum	; формирование длинного целого
    	add  esp, 8	; удаление параметров из стека
    	lea  dx, prmpt2 ; адрес выводимого текста
    	mov  ah, 09	; код функции DOS
    	int  21h	; вывод текста на экран
    	lea  eax, symbuf; адрес текстового буфера 
    	push eax	; запись адреса в стек
    	call _input	; ввод числа с клавиатуры
    	add  esp, 4	; удаление параметров из стека
    	lea  eax, symbuf; адрес текстового буфера 
    	push eax	; запись адреса в стек
    	lea  eax, subtr	; адрес вычитаемого
    	push eax	; запись адреса в стек
    	call _decnum	; формирование длинного целого
    	add  esp, 8	; удаление параметров из стека
    ;	Сравнение количества разрядов у операндов
    	xor  ebx, ebx	; ebx =0, код для заполнения при расширении
    	mov  eax, decrem; в eax размер уменьшаемого
    	sub  eax, subtr	; сравниваем размеры чисел
    	je   lnsb	; равное количество разрядов
    	ja   @F		; уменьшаемое длиннее
    	neg  eax	; eax = 0 - eax, меняем знак разнисти
    	push eax	; сохраняем в стеке
    	lea  eax, decrem; адрес расширяемого числа
    	jmp  ext	; переход на запись параметров
    @@:	push eax	; количество добавляемых разрядов
    	lea  eax, subtr	; адрес вычитаемого
    ext:	push ebx	; код для заполнения новых разрядов
    	push eax	; адрес decrem или subtr
    	call _lngext	; расширение числа
    	add  esp, 12	; удаление параметров из стека
    ;	Вычитание операндов имеющих равное количество разрядов
    lnsb:	lea  dx, prmpt3 ; адрес выводимого текста
    	mov  ah, 09	; код функции DOS
    	int  21h	; вывод текста на экран
    	lea  eax, decrem; адрес уменьшаемого
    	push eax	; сохранение адреса
    	lea  eax, subtr	; адрес вычитаемого
    	push eax	; сохранение адреса
    	lea  eax, differ; адрес разности
    	push eax	; сохранение адреса
    	call _lngsub	; вычитание длинных чисел
    	add  esp, 12	; удаление параметров из стека
    ;	Проверка знака разности и инверсия отрицательного числа
    	lea  eax, differ; адрес разности
    	mov  ebx, differ; количество разрядов у разности
    	cmp  [eax+4*ebx], -1; проверка кода старшего разряда
    	jne  @F		; разность - положительное число
    	dec  differ	; исключаем старший разряд
    	push eax	; адрес исходного числа
    	push eax	; адрес инвертированного числа
    	call _lnginv	; изменение знака у разности
    	add  esp, 8	; удаление параметров из стека
    	lea  dx, prmpt5 ; адрес текста содержащего знак минус
    	mov  ah, 09	; код функции DOS
    	int  21h	; вывод знака минус
    @@:	lea  eax, differ; адрес разности
    	push eax	; запись адреса в стек
    	lea  eax, dupnum; адрес для дубликата
    	push eax	; запись адреса в стек
    	call _lngdup	; создание копии числа
    	add  esp, 8	; удаление параметров из стека
    	lea  eax, dupnum; адрес копии числа
    	push eax	; запись адреса в стек
    	lea  eax, symbuf; адрес текстового буфера
    	push eax	; запись адреса в стек
    	call _decdig	; преобразование в ASCII
    	add  esp, 8	; удаление параметров из стека
    	lea  eax, symbuf; адрес текстового буфера
    	push eax	; запись адреса в стек
    	call _outbuf	; вывод десятичного числа
    	add  esp, 4	; удаление параметров из стека
    ;	Вопрос оператору и ожидание его реакции
    ask:	lea  dx, prmpt4 ; адрес выводимого текста
    	mov  ah, 09	; код функции DOS
    	int  21h	; вывод текста на экран
    GetChar:mov  ah, 1	; код функции "проверка готовности"
    	int  16h	; обращение к BIOS
    	jz   GetChar	; символ не введен
    	xor  ah, ah	; код функции "чтение символа в al"
    	int  16h	; обращение к BIOS
    	cmp  al, 'Y'	; введена буква Y ?
    	je   @F		; -> да
    	cmp  al, 'y'	; введена буква y ?
    	jne  eoprg	; -> нет, конец работы
    @@:	jmp  redo	; повторить еще раз
    eoprg:  mov  ax, 4C00h  ; ax = код завеpшения задачи
    	int  21h	; возвpат в DOS
    ;
    	END  Start
    
     
  2. ReaD

    ReaD Новичок

    Регистрация:
    16 апр 2008
    Сообщения:
    10
    Симпатии:
    0
    Баллы:
    0
    Функции:
    Код:
    ;	Преобразование  длинного целого  числа в строку цифр
    ;	в коде ASCII. Количество цифр  содержащихся в  числе
    ;	находится в младшем (нулевом) слове выходного буфера. 
    ;
    	PUBLIC	_decdig
    	ASSUME	cs:subr
    subr	SEGMENT	 word public 'subr'
     	.486
     ;	Размещение параметров в стеке:
     ;	[esp+8] - адрес преобразуемого длинного числа (X)
     ;	[esp+4] - адрес буфера для записи строки ASCII символов (Y)
     ;
    _decdig	proc far
    	mov  edi, [esp+8]; в edi адрес преобразуемого числа X
    	mov  ebx, [edi]	 ; ebx  = X(0), размер преобразуемого числа
    	mov  esi, [esp+4]; в esi адрес буфера для записи символов Y
    	inc  esi	 ; esi = esi + 1
    	jmp  @F		 ; на начало внешнего цикла
    ;	Внутренний цикл деления на 10
    innrlp:	mov  eax, [edi+ecx*4]; eax = X(i), чтение очередного разряда числа
    	div  _ddten	 ; edx:eax / 10, деление
    	mov  [edi+ecx*4], eax; X(i) = eax, запись частного в память
    	loop innrlp	 ; управление повторами цикла (i = i - 1)
    ;	Запись ASCII кода цифры в выходной массив
    extrlp:	inc  esi	 ; j = j + 1, адрес для записи цифры
    	add  dl, '0'	 ; преобразование цифры в код ASCII
    	mov  [esi], dl	 ; Y(j) = dl, запись очередной цифры в буфер
    ;	Подготовка к следующему делению и исключение пустых разрядов
    @@:	xor  edx, edx	 ; очистка старшей части делимого
    	mov  ecx, ebx	 ; новое количество повторов
    	or   [edi+ecx*4], edx; старшее слово содержит нуль?
    	jne  innrlp	 ; нет, на начало внутреннего цикла
    	dec  ebx	 ; уменьшение размера делимого
    	jne  @B		 ; возврат на проверку следующего разряда
    ;	Вычисление количества цифр в буфере
    	mov  eax, [esp+4]; в eax адрес начала буфера
    	sub  esi, eax	 ; esi = esi - eax, количество цифр 
    	dec  esi	 ; esi = esi - 1
    	jne  @F	 	 ; в буфере есть цифры
    	mov  [eax], word ptr 1; длинное число оказалось нулем
    	ret		 ; возврат на вызывающий модуль
    @@:	mov  ebx, esi	 ; ebx = esi, количество цифр в буфере
    	mov  word ptr [eax], bx ; запись количества цифр в буфере
    	ret		 ; возврат на вызывающий модуль
    _decdig	ENDP
    _ddten	dd 10	; используется при делении на 10
    subr	ENDS
    	END
    
    
    Код:
    ;	Процедура 8. Преобразование строки цифр в коде ASCII в длинное число
    	PUBLIC	 _decnum
     	ASSUME	 cs:subr
    subr	SEGMENT	word public 'subr'
      	 .486
     ;	Размещение параметров в стеке:
     ;	[esp+8]  - адрес строки цифр в коде ASCII (Y)
     ;	[esp+4]  - адрес формируемого длинного числа (X)
     ;
    _decnum	proc far
    	mov  esi, [esp+8]; в esi адрес строки цифр в коде ASCII Y
    	mov  edi, [esp+4]; в edi адрес формируемого длинного .числа X
    	xor  ecx, ecx	 ; ecx = 0, предварительная очистка
    	mov  [edi], ecx	 ; X(0) = 0, нулевой размер числа
    	inc  dword ptr [edi]; X(0) = 1, исходный размер числа
    	mov  [edi+4], ecx; X(1) = 0, очистка первого двойного слова
    	mov  cl, [esi]	 ; cl = Y(0), количество цифр в строке
    ;	Начало внешнего цикла формирования длинного числа
    nxtdig:	xor  ebx, ebx	 ; ebx = 0, смещение для указателей адресов
    	push ecx	 ; сохранение счетчика цифр в строке
    	mov  ecx, [edi]	 ; ecx = X(0), текущий размер числа
    	mov  edx, ebx	 ; edx = 0, очистка старшей части множимого
    	mov  eax, ebx	 ; eax = 0
    	mov  al, [esi+1] ; al = Y(j), код очередной цифры
    	sub  al, '0'	 ; al = al - 30h, вычитание ASCII кода нуля
    ;	Цикл умножения формируемого числа на 10
    lpmul:	xchg eax, [edi+ebx*4+4]	; перестановка: eax = X(i), X(i) = eax
    	mul  _ddten	 ; edx:eax = eax*10
    	add  [edi+ebx*4+4], eax	; X(i) = X(i) = eax, запись результата
    	adc  edx, 0	 ; edx = edx + C, учет возможного переполнения
    	inc  ebx	 ; ebx = ebx + 1, смещение для следующего слова
    	mov  eax, edx	 ; eax = edx, пересылка старшей части произведения
    	loop lpmul	 ; управление повторами цикла
    	or   edx, edx	 ; есть новый разряд у формируемого  числа?
    	Je   @F		 ; -> нет
    	mov  [edi+ebx*4+4], edx	; X(i+1) = edx, запись в новый разряд
    	inc  dword ptr [edi]	; X(0) = X(0) + 1, увеличиваем размер числа
    @@:	pop  ecx	 ; ecx = текущее количество цифр в строке
    	inc  esi	 ; esi = esi + 1, равносильно j = j + 1
    	loop nxtdig	 ; управление повторами внешнего цикла
    	ret 		 ; возврат на вызывающий модуль
    _decnum	ENDP
    _ddten	dd 10		 ; используется при умножении на 10
    subr 	ENDS
    	END
    
    
    Код:
    ;	Преобразование  длинного  числа в последовательность
    ;	шестнадцатеричных цифр в коде ASCII. Количество цифр
    ;	содержащихся в числе  находится  в младшем (нулевом)
    ;	             слове выходного буфера.
    ;
            PUBLIC  _hexdig
    	ASSUME  cs:subr
    subr	SEGMENT word public 'subr'
            .486
    ;
    ;       Размещение параметров в стеке:
    ;	[esp+4] - адрес выходного буфера
    ;	[esp+8] - адрес длинного числа
    ;
    _hexdig	proc far
    	mov  edi, [esp+8]; в edi адрес выводимого числа
    	mov  ecx, [edi]	 ; в ecx количество разрядов в числе
    	shl  ecx, 2	 ; в ecx количество байтов в числе
    	mov  ebx, 4	 ; смещение для младшего байта
    	mov  esi, [esp+4]; в esi выходного адрес буфера
    	mov  edx, ecx	 ; в edx количество байтов в числе
    	shl  edx, 1	 ; в edx количество тетрад в числе
    	mov  [esi], dx	 ; запись в выходной буфер
    	inc  esi	 ; коррекция адреса
    	inc  esi	 ; коррекция адреса
    ;	Цикл преобразования числа в шестнадцатиричные цифры
    lpout:	mov  al, [edi+ebx]; чтение очередного байта числа
    	push ax		 ; сохранение байта в стеке
    	and  al, 0Fh	 ; выделение младшей тетрады
    	add  al, 30h	 ; преобразование в код ASCII
    	cmp  al, 39h	 ; цифра больше чем 9 ?
    	jbe  $+4	 ; -> нет
    	add  al, 07	 ; да, формируем код буквы от A до F
    	mov  [esi], al	 ; запись в выходной буфер
    	inc  esi	 ; адрес следующего байта
    	pop  ax		 ; восстановление содержимого байта
    	shr  al, 04	 ; выделение старшей тетрады
    	add  al, 30h	 ; преобразование в код ASCII
    	cmp  al, 39h	 ; цифра больше чем 9 ?
    	jbe  $+4	 ; -> нет,
    	add  al, 07	 ; да, формируем код буквы от A до F
    	mov  [esi], al	 ; запись в выходной буфер
    	inc  esi	 ; адрес следующего байта буфера
    	inc  ebx	 ; адрес следующего байта числа
    	loop lpout	 ; управление повторами цикла
    	ret  		 ; возврат на вызывающий модуль
    _hexdig	ENDP
    subr    ENDS
    	END
    
    
    Код:
    ;	Запись в буфер десятичных цифр, вводимых с клавиатуры
    ;	  количество цифр не более 255, кодировка - ASCII.
    ;        Признак конца ввода Esc, клавиша Enter не работает.
    ;
            PUBLIC  _input
    	ASSUME  cs:subr
    subr	SEGMENT word public 'subr'
            .486
    ;	Размещение параметров в стеке:
    ;	[esp+4]  - буфер для записи кодов цифр
    ;
    _input	proc far
    	mov  edi, [esp+4]; в edi адрес буфера
    	xor  ecx, ecx	 ; количество символов в буфере
    	xor  ebx, ebx	 ; текущая позиция
    Insym:	call GetKey	 ; ввод очередного символа
    	jc   no_digit	 ; символ не цифра
    	cmp  ecx, ebx	 ; курсор в конце строки ?
    	jne  @F		 ; -> нет
    	inc  ecx	 ; количество символов в буфере
    @@:	inc  ebx	 ; позиция для записи цифры
    	mov  [edi+ebx], al; запись цифры в буфер
    	call OutSym	 ; эхо - вывод цифры на экран
    	jmp  short Insym ; на продолжение ввода
    ;	Код символа меньше кода нуля
    no_digit:cmp  al, 1Bh	 ; введен символ Esc ?
    	je   _Esc	 ; -> да, конец ввода
    	cmp  al, 0Dh	 ; введен символ Cr ?
    	je   Insym	 ; -> да, символ игнорируется
    	cmp  al, 0Ah	 ; введен символ Lf ?
    	je   Insym	 ; -> да, символ игнорируется
    	cmp  al, 08	 ; введен символ Backspace ?
    	je   _BS	 ; -> да, на удаление последней цифры
    	or   al, al	 ; введен scan code ?
    	je   scn_cod	 ; -> да
    bad_sym:call _Bell	 ; гудок
    	jmp  Insym	 ; продолжение ввода
    _Esc:	mov  [edi], cl	 ; количество введенных цифр
    	call CrLf	 ; переход на новую строку
    	ret  4		 ; возврат на вызывающий модуль
    _BS:	call OutSym	 ; возврат на шаг назад
    	mov  al, 20h	 ; код символа "пробел"
    	call Outsym	 ; стирание последней цифры
    	mov  al, 08	 ; код символа "возврат на шаг"
    	call Outsym	 ; возврат на шаг назад
    	dec  ecx	 ; уменьшение счетчика
    	mov  ebx, ecx	 ; копия для перемещений
    	jmp  Insym	 ; на продолжение ввода
    ;	Расшифровка и исполнение scan кодов
    scn_cod:cmp  ax, 4B00h	 ; символ "левая стрела"
    	je   _Left	 ; -> да
    	cmp  ax, 4D00h	 ; символ "правая стрелка"
    	je   _Right	 ; -> да
    	cmp  ax, 4700h	 ; символ "Home" ?
    	je   _Home	 ; -> перемещение в начало буфера
    	cmp  ax, 4F00h	 ; символ "End" ?
    	je   _End	 ; -> перемещение в конец буфера
    	cmp  ax, 5200h	 ; символ "Ins" ?
    	je   _Ins 	 ; -> вставка пробела
    	cmp  ax, 5300h	 ; символ "Del" ?
    	je   _Del	 ; -> удаление цифры
    	cmp  ax, 4800h	 ; символ "стрелка вверх" ?
    	je   _Up	 ; -> на предыдущую строку
    	cmp  ax, 5000h	 ; символ "стрелка вниз" ?
    	je   _Down	 ; -> на следующую строку
    	cmp  ax, 4900h	 ; символ "PgUp" ?
    	je   _PgUp	 ; -> в начало текста
    	cmp  ax, 5100h	 ; символ "PgDn" ?
    	je   _PgDn	 ; -> в конец текста
    @@:	jmp  bad_sym	 ; недопустимый символ
    _Left:	or   ebx, ebx	 ; достигнуто начало буфера ?
    	je   @B		 ; -> да
    	mov  al, 08	 ; код символа "возврат на шаг"
    	call OutSym	 ; перемещение на шаг влево
    	dec  ebx	 ; ebx = ebx - 1
    	jmp  Insym	 ; продолжение ввода
    _Right:	cmp  ebx, ecx	 ; символ в конце строки ?
    	je   @B		 ; -> да
    	inc  ebx	 ; коррекция позиции в буфере
    	call Getpos	 ; чтение текущей позиции курсора
    	inc  dl		 ; увеличение номера столбца
    	jmp Putpos	 ; установка следующей столбца
    _Home:	call Getpos	 ; чтение текущей позиции курсора
    	sub  byte ptr saveebx, dl; коррекция позиции в буфере
    	xor  dl, dl	 ; очистка номера столбца
    	jmp  Putpos	 ; перемещение в начало строки
    _End:	mov  edx, ecx	 ; edx = ecx
    	sub  edx, ebx	 ; edx = esx - ebx
    	cmp  edx, 80	 ; до конца текста меньше 80-ти цифр ?
    	jae  @F		 ; -> нет
    	add  ebx, edx	 ; коррекция позиции в буфере
    	call Getpos	 ; чтение текущей позиции курсора
    	add  dl, byte ptr saveedx ; номер последнего столбца
    	jmp  Putpos	 ; перемещение в конец строки
    @@:	call Getpos	 ; чтение позиции курсора
    	sub  byte ptr saveebx, dl; bl = bl - dl
    	mov  dl, 79	 ; для перемещения в конец строки
    	add  byte ptr saveebx, dl; коррекция позиции в буфере
    	jmp  Putpos	 ; перемещение в конец строки
    @@:	jmp  bad_sym	 ; недопустимый символ
    _Up:	cmp  ebx, 80	 ; курсор на первой строке ?
    	jb   @B		 ; -> да
    	sub  ebx, 80	 ; коррекция позиции в буфере
    	call Getpos	 ; чтение позиции курсора
    	dec  dh		 ; номер предыдущей строки
    	jmp  Putpos	 ; переход на предыдущую строку
    _Down:	mov  eax, ecx	 ; eax = ecx
    	sub  eax, ebx	 ; eax = ecx - ebx
    	cmp  eax, 80	 ; до конца текста меньше 80 строк ?
    	jb   @B		 ; -> да
    	add  ebx, 80	 ; коррекция позиции в буфере
    	call Getpos	 ; чтение позиции курсора
    	inc  dh		 ; номер следующей строки
    	jmp  Putpos	 ; переход на следующую строку
    ;	Вставка пробела в позицию под курсором
    _Ins:	cmp  ecx, ebx	 ; курсор в конце строки ? 
    	je   @B		 ; -> да
    	call Getpos	 ; исходная позиция курсора
    	mov  newpos, edx ; сохранение исходной позиции
    	mov  ebx, saveebx; восстановление ebx
    	mov  ecx, saveecx; восстановление ecx
    	push ecx	 ; сохранение содержимого ecx
    	push ebx	 ; сохранение содержимого ebx
    	sub  ecx, ebx	 ; количество перемещаемых цифр
    	mov  edx, ' '	 ; в dl код символа пробел
    lpins:	inc  ebx	 ; номер позиции в буфере
    	mov  al, [edi+ebx]; чтение цифры из буфера
    	xchg al, dl	 ; перестановка содержимого al и dl
    	mov  [edi+ebx], al  ; запись цифры в буфер
    	call OutSym	 ; вывод перемещенной цифры
    	loop lpins	 ; управление повторпми цикла
    	mov  al, dl	 ; последняя цифра строки
    	mov  [edi+ebx+1], al; запись в буфер
    	call Outsym	 ; вывод на экран
    	pop  ebx	 ; восстановление содержимого ebx
    	pop  ecx	 ; восстановление содержимого ecx
    	inc  ecx	 ; увеличение количества символов
    	call Getpos	 ; чтение текущей позиции курсора
    	mov  dx, word ptr newpos ;позиция пробела
    	jmp  Putpos	 ; перемещение курсора
    _Del:	cmp  ecx, ebx	 ; проверка позиции курсора
    	je   @B		 ; курсор в конце буфера
    	sub  ecx, ebx	 ; количество перемещаемых цифр
    lpdel:	inc  ebx	 ; смещение для следующей цифры
    	mov  al, [edi+ebx+1]; чтение цифры из буфера
    	mov  [edi+ebx], al  ; запись цифры в буфер
    	call OutSym	 ; вывод перемещенной цифры
    	loop lpdel	 ; управление повторами цицла
    	mov  al, 08	 ; код символа 
    	call OutSym	 ; перемещение курсора
    	dec  ebx	 ; коррекция текущей позиции
    	mov  ecx, ebx	 ; количество символов в буфере
    	jmp  Insym	 ; продолжение ввода
    _PgUp:	mov  eax, ebx	 ; eax = ebx
    	call cnvrt	 ; позиция ebx на экране
    	xor  ebx, ebx	 ; ebx = 0
    	call Getpos	 ; текущая позиция курсора
    	sub  dx, word ptr saveedx; координаты начала текста
    	jmp  Putpos	 ; переход в начало текста
    _PgDn:	mov  eax, ecx	 ; eax = ecx
    	sub  eax, ebx	 ; eax = ecx - ebx
    	call cnvrt	 ; пересчет разности в позицию
    	mov  ebx, ecx	 ; ebx = ecx
    	call Getpos	 ; текущая позиция курсора
    	add  dx, word ptr saveedx; координаты конца текста
    	jmp  Putpos	 ; переход в конец текса
    _input	ENDP
    ;
    ;	Пересчет количества символов в колонки и столбцы
    cnvrt:	mov  dl, 80	; dl = 80
    	div  dl		; ah:al = ax/80
    	xchg ah, al	; перестановка
    	mov  dx, ax	; dx = ax
    	ret		; возврат на вызывающий модуль	
    ;	Подпрограмма ввода символа с клавиатуры в регистр AL
    GetKey:	mov  ah, 1	; код функции "проверка готовности"
    	int  16h	; обращение к BIOS
    	jz   GetKey	; символ не введен
    	xor  ah, ah	; код функции "чтение символа в al"
    	int  16h	; обращение к BIOS
    	cmp  al, '0'	; код символа < кода нуля ?
    	jb   @F		; -> да, символ не цифра
    	cmp  al, '9'	; код символа > кода девятки
    	ja   @F		; -> да, символ не цифра
    	clc		; символ цифра, С=0
    	ret		; возврат на вызывающий модуль
    @@:	stc		; символ не цифра, С=1
    	ret		; возврат на вызывающий модуль
    ;
    ;       Вывод символа, ASCII код которого находится в al
    OutSym:	push ebx	; сохранение содержимого ebx
    	mov  ah, 0Eh	; ah = код функции BIOS
    	mov  bx, 07h	; цвет переднего плана (цифр)
    	int  10h	; обращение к BIOS для вывода символа
    	pop  ebx	; восстановление содержимого ebx
    	ret		; возарат на вызывающий модуль
    ;
    ;       Переход к началу следующей строки (вывод символов CR и LF)
    CrLf:	push eax	; сохранение содержимого eax
    	mov  al, 0Dh	; al = код символа "возврат каретки"
    	call outsym	; переход в начало текущей строки
    	mov  al, 0Ah	; al = код символа "перевод строки"
    	call outsym	; переход на новую строку
    	pop  eax	; восстановление содержимого eax
    	ret		; возврат на вызывающий модуль
    ;
    ;	Чтение позиции курсора
    Getpos:	mov  saveebx, ebx; сохранение содержимого ebx
    	mov  saveecx, ecx; сохранение содержимого ecx
    	mov  saveedx, edx; сохранение содержимого edx
    	mov  ax, 0300h	; код функции BIOS
    	xor  bx, bx	; видео страница
    	int  10h	; чтение позиции курсора
    	ret		;
    ;	Установка позиции курсора
    Putpos:	mov  ax, 0200h	; код функции BIOS
    	xor  bx, bx	; видео страница
    	int  10h	; перемещение курсора
    	mov  ebx, saveebx; восстановление содержимого ebx
    	mov  ecx, saveecx; восстановление содержимого ecx
    	mov  edx, saveedx; восстановление содержимого edx
    	jmp  Insym	; на продолжение ввода
    ;
    ;
    ;	Звуковой сигнал
    _bell:	push ecx	; сохранение содержимого ecx
    	push edx	; сохранение содержимого edx
    	in   al, 61h	; чтение порта 61h
    	or   al, 03h	; установка двух младших битов
    	out  61h, al	; запись в порт 61h
    ;	Выдержка паузы, обязательно два вложеных цикла
    	mov  ecx, 10000h; ecx = 10000h
    l1:	mov  edx, 100h	; edx = 100h
    l2:	dec  edx	; edx = edx -1
    	jnz  l2		; переход пока не 0
    	loop l1		; управление повторами цикла
    ;	Восстановление исходного состояния
    	in   al, 61h	; чтение порта 61h
    	and  al, 0FCh	; очистка двух младших разрядов
    	out  61h, al	; запись в порт 61h
    	pop  edx	; восстановление содержимого edx
    	pop  ecx	; восстановление содержимого ecx
    	ret		; возврат на вызывающий модуль
    ;	Группа переменных используемых при смене позиции курсора
    saveebx dd   0		; для сохранения ebx
    saveecx dd   0		; для сохранения ecx
    saveedx dd   0		; для сохранения edx
    newpos	dd   0		; для сохранения исходной позиции
    subr    ENDS
    	END
    
    
    Код:
    ;	Процедура 1. Сложение длинных положительных чисел
    	PUBLIC	_lngadd
    	ASSUME	cs:subr
    subr	SEGMENT	 word public 'subr'
     	.486
     ;	Размещение параметров в стеке:
     ;	[esp+12] - адрес первого слагаемого
     ;	[esp+8]  - адрес второго слагаемого
     ;	[esp+4]  - адрес для записи суммы
     ;
    _lngadd	proc far
    	mov  edi, [esp+12]; в edi адрес первого слагаемого (X)
    	mov  eax, [edi]   ; в eax размер первого слагаемого
    	mov  esi, [esp+8] ; в esi адрес второго слагаемого (Y)
    	mov  ecx, [esi]   ; в ecx размер второго слагаемого
    	mov  ebx, [esp+4] ; в ebx адрес для записи суммы (Z)
    ;	Запись в регистры esi и ecx адреса и размера короткого слагаемого
    	cmp  ecx, eax	  ; ecx =< eax ?
    	jbe  @F		  ; -> да !
    	xchg eax, ecx	  ; в ecx размер короткого слагаемого
    	xchg edi, esi	  ; в esi адрес короткого слагаемого
    @@:	mov  [ebx], eax	  ; предварительный размер суммы
    	xor  eax, eax	  ; eax = 0, смещение для указателей адресов
    	pushf		  ; сохранение флагов, С = 0
    ;	Основной цикл сложения чисел
    mainlp:	mov  edx, [edi+eax*4+4]	; edx = X(i)
    	popf		; восстановление флагов, C = C(i-1)
    	adc  edx, [esi+eax*4+4]	; edx = X(i) + Y(i) + C (i-1)
    	mov  [ebx+eax*4+4], edx	; Z(i) = edx (запись результата)
    	pushf		  ; сохранение флагов
    	inc  eax	  ; eax = eax + 1, смещение для следующего разряда
    	loop mainlp	  ; управление повторами цикла
    	mov  ecx, [ebx]	  ; в ecx размер длинного слагаемого
    	sub  ecx, eax	  ; ecx = ecx - eax, размер остатка
    	je   final	  ; -> остаток равен нулю
    ;	Обработка остатка длинного слагаемого
    rmndlp:	xor  edx, edx	  ; edx = 0
    	popf		  ; восстановление флагов, C = C(i-1)
    	adc  edx, [edi+eax*4+4]	; edx =	0 + X(i) + C(i-1)
    	mov  [ebx+eax*4+4], edx	; Z(i) = edx (запись результата)
    	pushf	 	  ; сохранение флагов
    	inc  eax	  ; eax = eax + 1, смещение для следующего разряда
    	loop rmndlp	  ; управление повторами цикла
    ;	Уточнение количества разрядов у суммы
    final:	popf		  ; восстановление флагов
    	jnc  @F		  ; -> при последнем сложении переноса не было
    	mov  dword ptr [ebx+eax*4+4], 1; Z(i)=1, дополнительный разряд суммы
    	inc  dword ptr [ebx]	; Z(0)=Z(0)+1, коррекция количества разрядов
    @@:	ret		  ; возврат на вызывающий модуль
    _lngadd	ENDP
    subr	ENDS
    	END
    
    
    Код:
    ;	Процедура 6. Деление длинного числа на двойное слово
     	PUBLIC	_lngdiv
    	ASSUME 	cs:subr
    subr	SEGMENT	word public 'subr'
     	.486
     ;	Размещение параметров в стеке:
     ;	[esp+12] - адрес длинного числа (делимого)
     ;	[esp+8] - значение делителя
     ;	[esp+4] - адрес частного (результата) 
     ;
    _lngdiv	proc far
    	mov  edi, [esp+12]; в edi адрес делимого
    	mov  ecx, [edi]	  ; в ecx размер делимого
    	mov  ebx, [esp+8] ; в ebx значение делителя
    	mov  esi, [esp+4] ; в esi адрес для записи частного
    	mov  [esi], ecx	  ; в esi(0) предварительный размер частного
    	xor  edx, edx	  ; edx = 0, очистка старшей части первого делимого
    ;	Цикл деления длинного числа на 32-х разрядное
    divlp:	mov  eax, [edi+ecx*4]; eax = edi(i), очередная часть делимого
    	div  ebx	  ; eax:edx = edx:eax/ ebx, деление
    	mov  [esi+ecx*4], eax; edi(i) = eax, запись частного в память
    	loop divlp	  ; управление повторами цикла (i = i - 1)
    ;	Проверка содержимого старшего разряда частного
    	mov  eax, [esi]	  ; eax = esi(0), размер частного
    	cmp  [esi+eax*4], ecx; старший разряд частного пустой ?
    	jne  @F		  ; -> нет
    	dec  dword ptr [esi] ; Z(0) = Z(0) - 1, исключение пустого разряда
    @@:	ret		  ; возврат на вызывающий модуль
    _lngdiv	ENDP
    subr	ENDS
    	END
    
    
    Код:
    ;	Процедура копирования (дублирования) длинного числа
    ;
            PUBLIC  _lngdup
    	ASSUME  cs:subr
    subr	SEGMENT word public 'subr'
            .486
    ;	Размещение параметров в стеке:
    ;	[esp+8]  - адрес копируемого числа
    ;	[esp+4]  - адрес копии
    ;
    _lngdup	proc far
    	mov  esi, [esp+8]	; адрес копируемого числа
    	mov  edi, [esp+4]	; адрес копии числа
    	mov  ecx, [esi]		; размер исходного числа
    	mov  [edi], ecx		; запись размера в копию
    	xor  ebx, ebx		; смещение для индексных выражений
    ;	Цикл копирования исходного числа в расширенное
    lpcopy: mov  eax, [esi+ebx*4+4]	; чтение из исходного числа
    	mov  [edi+ebx*4+4], eax	; запись в расширенное число
    	inc  ebx		; увеличение смещения на 1
    	loop lpcopy		; управление повторами цикла
    	ret 			; возврат на вызывающий модуль
    _lngdup	ENDP
    subr    ENDS
    ;
    	END
    
    
    Код:
    ;	Процедура 3. Расширение длинного числа
     	PUBLIC	_lngext
     	ASSUME	cs:subr
    subr	SEGMENT	word public 'subr'
     	.486
     ;	Размещение параметров в стеке:
     ;	[esp+12] - количество добавляемых разрядов
     ;	[esp+8]  - код заполнения
     ;	[esp+4]  - адрес расширяемого числа
     ;
    _lngext	proc far
    	mov  esi, [esp+4]; в esi адрес расширяемого числа
    	mov  ebx, [esi]	 ; количество разрядов в числе
    	inc  ebx	 ; смещение для добавляемых разрядов
    	mov  ecx, [esp+12]; в ecx количество добавляемых разрядов
    	add  [esi], ecx	 ; количество разрядов у расширенного числа
    	mov  eax, [esp+8]; в eax число для заполнения 
    ;	Копирование разрядов исходного числа в расширенное
    lpext:	mov  [edi+ebx*4+4], eax	;запись очередного разряда
    	inc  ebx	 ; ebx = ebx + 1, смещение для следующего разряда
    	loop lpext	 ; управление повторами цикла
    	ret 		 ; возврат на вызывающий модуль
    _lngext	ENDP
    subr	ENDS
    	END
    
    
    Код:
    ;	Процедура 4. Изменение знака (инверсия) длинного числа
     	PUBLIC	_lnginv
     	ASSUME	cs:subr
    subr	SEGMENT word public 'subr'
    .486
     ;	Размещение параметров в стеке:
     ;	[esp+8]  - адрес исходного (инвертируемого) числа (X)
     ;	[esp+4]  - адрес результата (инвертированного число) (Y)
     ;
    _lnginv	proc far
    	mov  edi, [esp+8]; в edi адрес исходного числа X
    	mov  ecx, [edi]	 ; в ecx размер исходного числа X
    	mov  esi, [esp+4]; в esi адрес для записи результата Y
    	mov  [esi], ecx	 ; Y(0) = X(0),. запись размера результата 
    	xor  ebx, ebx	 ; ebx = 0, смещение для указателей адресов
    	pushf		 ; C(0) = 0, сохранение флагов
    ;	Цикл изменения знака длинного числа
    inverlp:xor  eax, eax	 ; eax = 0
    	popf		 ; восстановление флагов, C = C(i-1)
    	sbb  eax, [edi+ebx*4+4]	; eax = eax - X(i) - C(i-1)
    	mov  [esi+ebx*4+4], eax	; Y(i) = eax, запись результата
    	pushf		 ; сохранение флагов, C = C(i)
    	inc  ebx	 ; ebx = ebx + 1, смещение для следующего разряда
    	loop inverlp	 ; управление повторами цикла
    	popf		 ; очистка стека
    	ret 		 ; возврат на вызывающий модуль
    _lnginv	ENDP
    subr 	ENDS
    	END
    
    
    Код:
    ;	Процедура 5. Умножение длинных чисел
    	PUBLIC  _lngmul
    	ASSUME	cs:subr
    subr	SEGMENT	word public 'subr'
     	.486
     ;	Размещение параметров в стеке:
     ;	[esp+12] -  адрес множимого X
     ;	[esp+8]  -  адрес множителя Y
     ;	[esp+4]  -  адрес произведения Z
     ;
    _lngmul	proc far
    	mov  edi, [esp+12]; в edi адрес множимого X
    	mov  ebp, [esp+8] ; в ebp адрес множителя Y
    	mov  ecx, ds:[ebp]; ecx = Y(0), размер множителя
    	add  ecx, [edi]	  ; ecx = ecx + X(0), возможный размер произведения
    	mov  esi, [esp+4] ; в esi адрес произведения Z
    	mov  [esi], ecx	  ; Z(0) = X(0) + Y(0), запись размера произведения
    	xor  eax, eax	  ; eax = 0, используется в цикле очистки
    ;	Цикл очистки разрядов произведения начиная с конца массива
    clrlp:	mov  [esi+ecx*4], eax;  Z(i) = 0, очистка очередного разряда
    	loop clrlp	  ; управление повторами цикла ( i = i - 1)
    	mov  ecx, ds:[ebp]; ecx = Y(0), счетчик для внешнего цикла
    ;	Внешний цикл управляет повторами цикла умножения
    extrlp:	push ecx	  ; сохранение в стеке содержимого ecx 
    	mov  ecx, [edi]	  ; ecx = X(0), счетчик для цикла умножений
    	xor  ebx, ebx	  ; ebx = 0, смещение для указателей адресов
    	pushf		  ; сохранение регистра флагов, С = 0
    ;	Внутренний цикл формирует произведение длинных чисел
    innrlp:	mov  eax, [edi+ebx*4+4]  ; eax = X(i), очередной разряд множимого
    	mul  dword ptr ds:[ebp+4]; edx:eax = X(i)*Y(j), произведение 64-х разрядное
    	add  [esi+ebx*4+4], eax	 ; Z(i+j) = Z(i+j) + eax
    	adc  edx, 0	  ; edx = edx + C, учет возможного переполнения
    	popf		  ; восстановление флагов, C(i) = C(i-1)
    	adc  [esi+ebx*4+8], edx	 ; Z(i+j+1) = Z(i+j+1) + edx + C(i-1)
    	pushf		  ; сохранение флагов (сохранение C(I))
    	inc  ebx	  ; ebx = ebx + 1, равносильно i = i + 1
    	loop innrlp	  ; управление повторами цикла умножения
    	popf		  ; восстановление флагов
    	jnc  @F		  ; - > при выходе из цикла переполнения не было 
    	inc  dword ptr [esi+ebx*4+8]; Z(i+j+2) = 1, учитываем переполнение
    @@:	add  esi, 4	  ; esi = esi + 4, равносильно j=j+1 для массива Y
    	add  ebp, 4	  ; ebp = ebp + 4, равносильно j=j+1 для массива Z
    	pop  ecx	  ; восстановление счетчика внешнего цикла
    	loop extrlp	  ; управление повторами внешнего цикла
    ;	Исключение пустого старшего разряда произведения
    	cmp  [esi+ebx*4], ecx; старший разряд произведения пустой? 
    	jne  @F		  ; - > нет, выход из процедуры
    	mov  eax, [esp+4] ; да, запись в eax адреса X
    	dec  dword ptr [eax]; Z(0)=Z(0)-1, коррекция количества разрядов
    @@:	ret 		  ; возврат на вызывающий модуль
    _lngmul	ENDP
    subr	ENDS
    	END
    
    
    Код:
    ;	Процедура 2. Вычитание двух длинных чисел
     	PUBLIC	_lngsub
    	ASSUME	cs:subr
    subr	SEGMENT	word public 'subr'
     	.486
     ;	Размещение параметров в стеке:
     ;	[esp+12] - адрес уменьшаемого (X)
     ;	[esp+8]  - адрес вычитаемого (Y)
     ;	[esp+4]  - адрес разности (Z)
     ;
    _lngsub	proc far
    	mov  edi, [esp+12]; в edi адрес уменьшаемого (X)
    	mov  ecx, [edi]	  ; в ecx размер уменьшаемого
    	mov  esi, [esp+8] ; в esi адрес вычитаемого (Y)
    	mov  ebx, [esp+4] ; в ebx адрес разности (Z)
     	cmp  ecx, [esi]	  ; количество разрядов совпадает?
    	Je   @F	 	  ; -> да!
    	mov  dword ptr[ebx], 0	  ; нет! Z(0) = 0, разность не вычислялась
    	ret		  ; возврат на вызывающий модуль
    @@:	mov  [ebx], ecx	  ; Z(0) = ecx, ожидаемый размер разности
    	xor  eax, eax	  ; eax = 0, смещение для указателей адресов
    	pushf		  ; сохранение флагов, C(0) = 0
    ;	Цикл вычитания чисел
    substlp:mov  edx, [edi+eax*4+4]	; edx = X(i), очередной разряд уменьшаемого
    	popf		  ; восстановление флагов C = C(i-1)
    	sbb  edx, [esi+eax*4+4]	; edx = edx - Y(i) - C(i-1), вычисление разряда разности
    	mov  [ebx+eax*4+4], edx	; Z(i) = edx, запись разряда в выходной массив
    	pushf 		  ; сохранение флагов, C = C(i)
    	inc  eax	  ; eax = eax + 1, увеличение смещения адресов
    	loop substlp	  ; управление повторами цикла
    	popf		  ; восстановление флагов
    	jnc  @F		  ; разность положительна
    	dec  ecx	  ; ecx = 0FFFFFFFFh
    	mov  [ebx+eax*4+4], ecx; дополнительный разряд
    	inc  dword ptr [ebx]; увеличение количества разрядов
    	jmp  eop	  ; возврат на вызывающий модуль
    ;	Исключение пустых старших разрядов разности
    @@:	xchg eax, ecx	  ; перестановка: ecx = eax, eax = ecx
    	jmp  short eolp	  ; переход на управление повторами цикла
    delzero:cmp  [ebx+ecx*4+4], eax	; Z(i) = 0?
    	jne  eop		  ; -> нет, выход из цикла
    	dec  dword ptr [ebx]; Z(0)=Z(0) -1, уменьшение количества разрядов
    eolp:	loop delzero	  ; управление повторами цикла
    eop:	ret 		  ; возврат на вызывающий модуль
    _lngsub	ENDP
    subr	ENDS
    	END
    
    
    Код:
    ;	Вывод строки ASCII (содержимого буфера) на экран
    ;	Количество цифр указано в младшем (нулевом) слове
    ;	буфера содержащего строку цифр.
    ;
            PUBLIC  _outbuf
    	ASSUME  cs:subr
    subr	SEGMENT word public 'subr'
            .486
    ;	Размещение параметров в стеке:
    ;	[esp+4]  - адрес буфера, содержащего выводимую строку
    ;
    _outbuf	proc far
    	mov  edi, [esp+4]; адрес исходного числа
    	xor  ecx, ecx	 ; ecx = 0, очистка регистра
    	mov  cx, [edi]	 ; количество символов в буфере
    	inc  edi	 ; коррекция адреса
    ;	Цикл вывода символов начиная с конца буфера
    outscr:	mov  al, [edi+ecx]; чтение очередной цифры
    	mov  ah, 0Eh	 ; код функции BIOS
    	mov  bx, 07	 ; код цвета фона
    	int  10h	 ; вывод цифры на экран
    	loop outscr	 ; управление повторами цикла
    ;	Вывод завершен, выполняется переход на следующую строку
    	mov  al, 0Dh	 ; код сивола CR
    	mov  ah, 0Eh	 ; код функции BIOS
    	mov  bx, 07	 ; код цвета фона
    	int  10h	 ; переход в начало строки
    	mov  al, 0Ah	 ; код символа LF
    	mov  ah, 0Eh	 ; код функции BIOS
    	mov  bx, 07	 ; код цвета фона
    	int  10h	 ; переход на следующую строку
    	ret              ; возврат на вызывающий модуль
    _outbuf	ENDP
    subr    ENDS
    	END
    
    
    P.S. Соответственно ненужно все их вставлять в каждую программу:) там могут оказаться несколько лишних так про них можно вообще забыть
     

Поделиться этой страницей