Составить программу, вычисляющую сумму возрастающей арифметической прогрессии прямым суммированием слагаемых - 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
Решение задачи: «Составить программу, вычисляющую сумму возрастающей арифметической прогрессии прямым суммированием слагаемых»
; 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
, которая используется для перевода каретки.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д