Составить программу, вычисляющую сумму возрастающей арифметической прогрессии прямым суммированием слагаемых - Assembler

Узнай цену своей работы

Формулировка задачи:

Здравствуйте! имеется задание: Составить программу, вычисляющую сумму возрастающей арифметической прогрессии прямым суммированием слагаемых. Определить минимальное число слагаемых, нужных для переполнения двойного слова и вывести на экран число слагаемых и сумму в десятичной форме. Программа не должна выдавать ошибку переполнения. и код:
model tiny
.model tiny
.486
.code
assume cs:@code, ds:@code, es:@code, ss:@code
org 100h
 
begin:
 
mov ah, 0ah         ;ввод нулевого элемента
mov dx, offset a0
int 21h
 
mov ah, 09h             ;перевод каретки, чтобы вводимые числа
mov dx, offset car      ;не сливались
int 21h
 
mov ah, 0ah     ;ввод
mov dx, offset d
int 21h
 
mov ah, 09h             
mov dx, offset car  
int 21h
 
;///////////////////////////////////
;преобразование а0 из строки в число
 
xor ax, ax
xor ecx, ecx
mov si, offset a0       ;помещение в si адреса начала а0
inc si
mov al, [si]        ;в al - длина строки а0
inc si
                                    
cmp al, 10          ;реализация паскалевского оператора case на ассемблере,
ja err_inp          ;выбор производится по длине строки введенного числа
cmp al, 9
ja a0_10
cmp al, 8
ja a0_9
cmp al, 7
ja a0_8
cmp al, 6
ja a0_7
cmp al, 5
ja a0_6
cmp al, 4
ja a0_5
cmp al, 3
ja a0_4
cmp al, 2
ja a0_3
cmp al, 1
ja a0_2
 
jmp a0_1            ;else-часть case'а
 
a0_10:
mov al, byte ptr [si]   ;помещаем в al первый байт(символ) строки
sub al, '0'         ;вычтем код'0'(=30h), получим соотв.цифру
mov ebx, 1000000000 
mul ebx             ;помещаем выделенную цифру в 10й разряд
add ecx, eax        ;и добавляем ее к итоговому
inc si          ;переход к след.байту
 
xor eax, eax
 
a0_9:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 100000000  ;все то же, только цифра -> в 9й разряд
mul ebx
add ecx, eax
inc si
 
xor eax, eax
 
a0_8:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 10000000       ;8й разряд
mul ebx
add ecx, eax
inc si
 
xor eax, eax
a0_7:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 1000000        ;7й разряд
mul ebx
add ecx, eax
inc si
 
xor eax, eax
 
a0_6:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 100000         ;6й разряд
mul ebx
add ecx, eax
inc si
 
xor eax, eax
 
a0_5:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 10000          ;5й разряд
mul ebx
add ecx, eax
inc si
 
xor eax, eax
 
a0_4:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 1000           ;4й разряд
mul ebx
add ecx, eax
inc si
 
xor eax, eax
 
a0_3:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 100            ;3й разряд
mul ebx
add ecx, eax
inc si
 
xor eax, eax
 
a0_2:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 10         ;2й разряд
mul ebx
add ecx, eax
inc si
 
xor eax, eax
 
a0_1:
mov al, byte ptr [si]
sub al, '0'         
add ecx, eax        ;в 1й разряд записываем цифру без изменений

xor eax, eax
 
;преобразование str в int завершено
;           a0 - в ecx
;//////////////////////////////////
 
xor eax, eax
xor edx, edx
 
;///////////////////////////////////
;преобразование d из строки в число
 
mov si, offset d
inc si
mov al, [si]
inc si
 
cmp al, 10
ja err_inp
cmp al, 9
ja d_10
cmp al, 8
ja d_9
cmp al, 7
ja d_8
cmp al, 6
ja d_7
cmp al, 5
ja d_6
cmp al, 4
ja d_5
cmp al, 3
ja d_4
cmp al, 2
ja d_3
cmp al, 1
ja d_2
 
jmp d_1
 
d_10:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 1000000000
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_9:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 100000000
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_8:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 10000000
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_7:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 1000000
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_6:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 100000
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_5:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 10000
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_4:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 1000
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_3:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 100
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_2:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 10
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_1:
mov al, byte ptr [si]
sub al, '0'
add edx, eax
 
xor eax, eax
 
;преобразование str в int завершено
;           d - в edx
;//////////////////////////////////
 
xor eax, eax        ;подготовка счетчика 
push ecx            ;и стека к циклу
                ;в стеке будем хранить сумму арифм.прогрессии
progr:
pop ecx         ;извлекаем сумму
add ecx, edx        ;а0=а0+d
jb end_progr        ;если переполнение => выход
push ecx            ;иначе сохраняем сумму,
inc ax          ;увеличиваем счетчик шагов 
jmp short progr     ;и идем в начало цикла
 
end_progr:
 
;печать результатов:
 
call print10_pl pascal, eax, 0, 1, 0, 0, 0 
pop edx
call print10_pl pascal, edx, 0, 1, 0, 0, 0

err_inp:
;ошибка ввода числа, выходим из программы не делая ничего
 
mov ah, 4ch
int 21h

;-----------------------------------
;раздел процедур
 
print10_pl proc near    ;процедура вывода числа без знака, размером dd (10 симв.)
locals @@
                    ;аргументы процедуры:
  ;numb         ;Представляемое число, размером dd
 
  ;num_off          ;смещение строки из 10 символов, 
                    ;где содержится печатаемое число
 
  ;pp0          ;Признак печати, dw: 0-нет печати,
                    ;1-на экран, 2-в файл
 
  ;f_handle         ;Дескриптор файла, параметр значим при печати в файл
 
  ;zero         ;dw, 0-без печати ведущих нулей, 
                    ;отступ(beg) не работает
 
  ;beg          ;dw, отступ в знаках от начала печатаемого числа, <=9
 
;аргументы в обратном порядке
arg beg:word, zero:word, f_handle:word, pp0:word, num_off:word, numb:dword=args_size
 
push bp
mov bp, sp
push eax
push ebx
push cx
push edx
push si
 
mov cx, 10          ;задаем макс.длину десятичного числа
mov si, num_off
push cx
 
@p:
mov byte ptr [si], '0'  ;заполняем символами нуля
inc si
loop @p
 
pop cx
mov eax, numb           ;представляемое число
mov si, num_off     ;адрес результата для печати
add si, 9
mov ebx, 10         ;делитель для выделения десятичной цифры
 
@@pr:
mov edx, 0
div ebx
add dl, '0'         ;в dl - код десятичной цифры
mov byte ptr [si], dl
or eax, eax         ;проверка на нуль
jz short @@pr2
dec si
loop @@pr
 
@@pr2:              ;в si - адрес первой ведущей ненулевой цифры
cmp pp0, 0
je @@e6             ;выход без печати, если печатаем ноль
mov ah, 40h         ;печать числа в файл/на экран
 
mov cx, 10          ;макс.длина числа
mov dx, offset num_off
mov bx, 1
cmp pp0, 2
je @@e1
jmp short @@e2
 
@@e1:
mov bx, f_handle
@@e2:
cmp zero, 0
jne short @@e3
add cx, dx
sub cx, si
mov dx, si
jmp short @@e4
@@e3:
sub cx, beg
sub dx, beg
@@e4:
int 21h
 
@@e6:
pop si
pop edx
pop cx
pop ebx
pop eax
mov sp, bp          ;восстановление указателя стека к моменту входа
pop bp
ret args_size           ;очистка стека от шести параметров(4+2+2+2+2+2 байта)
 
print10_pl endp
 
;-----------------------------------
;раздел данных
 
a0 dd 10,?,10 dup(?)
d dd 10,?,10 dup(?)
car db 13,10,'$'        ;строка для перевода каретки
 
end begin
Не могу откомпилировать в masm32 выдает:

Решение задачи: «Составить программу, вычисляющую сумму возрастающей арифметической прогрессии прямым суммированием слагаемых»

textual
Листинг программы
; masm dos com #
.model tiny
.code
.486
org 100h
 
begin:  mov ah, 0ah         ;ввод нулевого элемента
mov dx, offset a0
int 21h
 
mov ah, 09h             ;перевод каретки, чтобы вводимые числа
mov dx, offset car      ;не сливались
int 21h
 
mov ah, 0ah     ;ввод
mov dx, offset d
int 21h
 
mov ah, 09h             
mov dx, offset car  
int 21h
 
;///////////////////////////////////
;преобразование а0 из строки в число
 
xor ax, ax
xor ecx, ecx
mov si, offset a0       ;помещение в si адреса начала а0
inc si
mov al, [si]        ;в al - длина строки а0
inc si
                                    
cmp al, 10          ;реализация паскалевского оператора case на ассемблере,
ja err_inp          ;выбор производится по длине строки введенного числа
cmp al, 9
ja a0_10
cmp al, 8
ja a0_9
cmp al, 7
ja a0_8
cmp al, 6
ja a0_7
cmp al, 5
ja a0_6
cmp al, 4
ja a0_5
cmp al, 3
ja a0_4
cmp al, 2
ja a0_3
cmp al, 1
ja a0_2
 
jmp a0_1            ;else-часть case'а
 
a0_10:
mov al, byte ptr [si]   ;помещаем в al первый байт(символ) строки
sub al, '0'         ;вычтем код'0'(=30h), получим соотв.цифру
mov ebx, 1000000000 
mul ebx             ;помещаем выделенную цифру в 10й разряд
add ecx, eax        ;и добавляем ее к итоговому
inc si          ;переход к след.байту
 
xor eax, eax
 
a0_9:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 100000000  ;все то же, только цифра -> в 9й разряд
mul ebx
add ecx, eax
inc si
 
xor eax, eax
 
a0_8:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 10000000       ;8й разряд
mul ebx
add ecx, eax
inc si
 
xor eax, eax
a0_7:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 1000000        ;7й разряд
mul ebx
add ecx, eax
inc si
 
xor eax, eax
 
a0_6:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 100000         ;6й разряд
mul ebx
add ecx, eax
inc si
 
xor eax, eax
 
a0_5:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 10000          ;5й разряд
mul ebx
add ecx, eax
inc si
 
xor eax, eax
 
a0_4:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 1000           ;4й разряд
mul ebx
add ecx, eax
inc si
 
xor eax, eax
 
a0_3:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 100            ;3й разряд
mul ebx
add ecx, eax
inc si
 
xor eax, eax
 
a0_2:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 10         ;2й разряд
mul ebx
add ecx, eax
inc si
 
xor eax, eax
 
a0_1:
mov al, byte ptr [si]
sub al, '0'         
add ecx, eax        ;в 1й разряд записываем цифру без изменений
 
 
xor eax, eax
 
;преобразование str в int завершено
;           a0 - в ecx
;//////////////////////////////////
 
xor eax, eax
xor edx, edx
 
;///////////////////////////////////
;преобразование d из строки в число
 
mov si, offset d
inc si
mov al, [si]
inc si
 
cmp al, 10
ja err_inp
cmp al, 9
ja d_10
cmp al, 8
ja d_9
cmp al, 7
ja d_8
cmp al, 6
ja d_7
cmp al, 5
ja d_6
cmp al, 4
ja d_5
cmp al, 3
ja d_4
cmp al, 2
ja d_3
cmp al, 1
ja d_2
 
jmp d_1
 
d_10:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 1000000000
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_9:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 100000000
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_8:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 10000000
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_7:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 1000000
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_6:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 100000
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_5:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 10000
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_4:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 1000
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_3:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 100
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_2:
mov al, byte ptr [si]
sub al, '0'
mov ebx, 10
push edx
mul ebx
pop edx
add edx, eax
inc si
 
xor eax, eax
 
d_1:
mov al, byte ptr [si]
sub al, '0'
add edx, eax
 
xor eax, eax
 
;преобразование str в int завершено
;           d - в edx
;//////////////////////////////////
 
xor eax, eax        ;подготовка счетчика 
push ecx            ;и стека к циклу
                ;в стеке будем хранить сумму арифм.прогрессии
progr:
pop ecx         ;извлекаем сумму
add ecx, edx        ;а0=а0+d
jb end_progr        ;если переполнение => выход
push ecx            ;иначе сохраняем сумму,
inc ax          ;увеличиваем счетчик шагов 
jmp short progr     ;и идем в начало цикла
 
end_progr:
 
;печать результатов:
push  0 
push  0 
push  0 
push  1 
push  0
push  eax
call print10_pl 
pop edx
push 0
push 0
push 0
push 1 
push 0
push edx
call print10_pl 
 
 
err_inp:
;ошибка ввода числа, выходим из программы не делая ничего
 
mov ah, 4Ch
int 21h
 
 
;-----------------------------------
;раздел процедур
 
print10_pl proc pascal beg:word, zero:word, f_handle:word, pp0:word, num_off:word, numb:dword  ;процедура вывода числа без знака, размером dd (10 симв.)
                    ;аргументы процедуры:
  ;numb         ;Представляемое число, размером dd
 
  ;num_off          ;смещение строки из 10 символов, 
                    ;где содержится печатаемое число
 
  ;pp0          ;Признак печати, dw: 0-нет печати,
                    ;1-на экран, 2-в файл
 
  ;f_handle         ;Дескриптор файла, параметр значим при печати в файл
 
  ;zero         ;dw, 0-без печати ведущих нулей, 
                    ;отступ(beg) не работает
 
  ;beg          ;dw, отступ в знаках от начала печатаемого числа, <=9
 
;аргументы в обратном порядке
 
push eax
push ebx
push cx
push edx
push si
 
mov cx, 10          ;задаем макс.длину десятичного числа
mov si, num_off
push cx
 
@p:
mov byte ptr [si], '0'  ;заполняем символами нуля
inc si
loop @p
 
pop cx
mov eax, numb           ;представляемое число
mov si, num_off     ;адрес результата для печати
add si, 9
mov ebx, 10         ;делитель для выделения десятичной цифры
 
@@pr:
mov edx, 0
div ebx
add dl, '0'         ;в dl - код десятичной цифры
mov byte ptr [si], dl
or eax, eax         ;проверка на нуль
jz short @@pr2
dec si
loop @@pr
 
@@pr2:              ;в si - адрес первой ведущей ненулевой цифры
cmp pp0, 0
je @@e6             ;выход без печати, если печатаем ноль
mov ah, 40h         ;печать числа в файл/на экран
 
mov cx, 10          ;макс.длина числа
lea dx,num_off
mov bx, 1
cmp pp0, 2
je @@e1
jmp short @@e2
 
@@e1:
mov bx, f_handle
@@e2:
cmp zero, 0
jne short @@e3
add cx, dx
sub cx, si
mov dx, si
jmp short @@e4
@@e3:
sub cx, beg
sub dx, beg
@@e4:
int 21h
 
@@e6:
pop si
pop edx
pop cx
pop ebx
pop eax
ret           ;очистка стека от шести параметров(4+2+2+2+2+2 байта)
 
print10_pl endp
 
;-----------------------------------
;раздел данных
 
a0 dd 10,?,10 dup(?)
d dd 10,?,10 dup(?)
car db 13,10,'$'        ;строка для перевода каретки
 
end begin

Объяснение кода листинга программы

Данный код на языке Assembler выполняет вычисление суммы арифметической прогрессии и выводит результат на экран или в файл. Процесс вычисления суммы арифметической прогрессии начинается с выбора длины введенного числа (код в переменной al). Затем, в зависимости от значения al, происходит переход к соответствующему блоку кода для вычисления суммы прогрессии. После вычисления суммы прогрессии, результат сохраняется в регистре ecx. Затем происходит преобразование числа в строку и сохранение этой строки в переменной d. Далее, код проверяет, было ли введено число, и, если нет, завершает работу программы. Если число было введено, код выводит его на экран или в файл. Процедура print10_pl используется для печати числа без знака размером 10 символов. Входные аргументы процедуры включают само число, смещение строки, признак печати и дескриптор файла. Процедура заполняет строку символами нуля, выделяет десятичную цифру и печатает число на экране или в файле. В конце кода определены данные, включая переменные a0 и d, которые используются для хранения чисел, и строку car, которая используется для перевода каретки.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

11   голосов , оценка 4.182 из 5
Похожие ответы