Ввести два 16-битовых целых числа А и В. Вычислить результат логического побитового исключающего ИЛИ чисел 10* - Assembler
Формулировка задачи:
Помогите найти ошибку. Все компилируется, но при запуске вылетает с ошибкой.
Заранее спасибо)
Листинг программы
- model small
- outmsg macro msg ; macros dlya vivoda na ekran
- push eax
- push edx
- mov ah,09h
- lea dx,msg
- int 21h
- pop edx
- pop eax
- endm
- .stack 100h ;zadaem razmer steka
- .data ;nachalo bloka peremennih
- MSG1 DB "Input A(0..255): ",'$'; zadaem strokovie peremennie
- MSG2 DB "Input B(0..255): ",'$'
- ERROR_MSG DB "Slishkom bolshoe chislo!",'$'
- .code ;nachalo bloka koda
- .486
- calc proc far ;procedura operacii
- ;vipolnyaem 6*B^2
- mov ecx,eax
- mov eax,ebx
- mul ebx
- mov ebx,eax
- mov eax,6
- mul ebx
- mov ebx,eax
- ; vipolnyaem A*10
- mov eax,10
- mul ecx
- xchg eax,ecx
- ;vipolnyaem pobitovoe logicheskoe ili resultat zanositsya v eax
- xor eax,ebx
- calc endp
- printRes proc
- test eax,eax
- jns nsig
- mov ecx,eax
- mov ah,02h
- mov dl,'-'
- int 21h
- mov eax,ecx
- neg eax
- nsig:
- xor ecx,ecx
- mov ebx,10
- nums:
- xor edx,edx
- div ebx
- push edx
- inc cx
- test eax,eax
- jnz nums
- mov ah,02h
- show:
- pop edx
- add dl,'0'
- int 21h
- loop show
- ret
- printRes endp
- MAIN: ;tochka vhoda v programmu
- mov ax,@data ;zadaem adress segmenta dannih
- mov ds,ax
- xor eax,eax ; eax = 0
- xor ebx,ebx ; ebx = 0
- xor ecx,ecx ; ecx = 0
- mov edx,10 ; stepen sistemi ischisleniya
- outmsg MSG1 ; Daem zapros na A
- INPUT_A:
- mov ch,01h;vvod s klaviaturi
- int 21h ;prerivanie
- je NEXT ;perehod k B
- sub cl,30h ;perevodim simvol v chislo
- cbw ;rasshiryaem do word
- mul edx ;primenyaem systemy ischisleniya
- add eax,ecx ;dobavlyaem vvedennuyu cifru k predidushemy chislu
- jmp INPUT_A ;povtoryaem cikl
- NEXT:
- outmsg MSG2 ; Daem zapros na B
- INPUT_B:
- mov ch,01h;vvod s klaviaturi
- int 21h ;prerivanie
- je END_INPUT ;okonchanie vvoda
- sub cl,30h ;perevodim simvol v chislo
- cbw ;rasshiryaem do word
- mul edx ;primenyaem systemy ischisleniya
- add ebx,ecx ;dobavleyaem vvedennuyu cifru k predidushemy chislu
- jmp INPUT_B ;povtoryaem cikl
- END_INPUT:
- cmp eax,255 ;proverka na dopustimost znacheniya
- ja ERROR
- cmp ebx,255 ;proverka na dopustimost znacheniya
- ja ERROR
- call calc
- ERROR:
- outmsg ERROR_MSG
- jmp EXIT
- EXIT:
- mov ax,4c00h
- int 21h
- end MAIN
Решение задачи: «Ввести два 16-битовых целых числа А и В. Вычислить результат логического побитового исключающего ИЛИ чисел 10*»
textual
Листинг программы
- .model small ;model pamati small
- outmsg macro msg
- push eax
- push edx
- mov ah,09h
- lea dx,msg
- int 21h
- pop edx
- pop eax
- endm
- .stack 256 ;stek zanimaet 256 baitov
- .data ;segment dannyh
- Mess1 db 'Vvedite chislo A (-224..+225): $'
- Mess2 db 'Vvedite chislo B (-224..+225): $'
- Exit_Mess db 10,13,'Nazhmite lubuju klavishu...$'
- error db "incorrect number$"
- buff db 6,7 Dup(?)
- .code
- .486
- ;procedura vychislaet 6*B^2 i A*10
- ; Znachenie B peredaetsa cherez registr bx
- ; Znachenie A peredaetsa cherez registr bp
- ;Rezultat vychislenij peredaetsa cherez registr ax.
- calc proc far
- mov ax,bx; zanosim B v ax
- mul bx ;umnojaem B na B
- mov bx,ax ;vozvrashaem resultat v bx
- mov ax,6 ;zanosim 6 v ax
- mul bx ;umnojaem B^2 na 6
- mov bx,ax ;vozvrashaem resultat 6*B^2
- ;vipolnyaem A*10
- mov ax,10 ;zanosim v ax 10
- mul bp ;umnojaem A na 10
- mov bp,ax ;vozvrashaem resultat
- xor bp,bx ;vipolnyaem pobitovoe logicheskoe ili resultat zanositsya v bp
- mov ax,bp ; otpravlyaem resultat v ax
- ret
- calc endp
- ;procedura vyvodit chislo iz registra ax na ekran
- prints proc ;pechataet soderjimoe ax
- mov cx,10 ;v cx zanosim delitel 10
- xor di,di ;ochistka di (kolichestvo cifr v chisle)
- ;esli ax<0, to pechataem '-' i delaem ax polozhitelnym
- or ax,ax ;proveraem ax
- jns conv ;esli ax>0 (SF=0), to perehod na metku conv
- push ax ;pomeschaem ax v stek
- mov dx,'-' ;zanosim v dx '-'
- mov ah,2 ;vyvod '-' na ekran
- int 21h
- pop ax ;vosstanavlivaem ax
- neg ax ;delaem ax polozhitelnym
- conv:
- xor dx,dx ;ochistka dx
- div cx ;dl = ax mod 10,
- add dl,'0' ;perevodim ostatok v simvol
- inc di ;uvelichivaem kolichestvo cifr v chisle na 1
- push dx ;ostatok pomeschaem v stek
- or ax,ax ;proveraem ax (chastnoe)
- jnz conv ;esli ax<>0, to perehod na metku conv
- ;i povtoraem delenie
- ;vyvod cifr iz steka na ekran
- print:
- pop dx ;izvlekaem iz steka ocherednoj simvol
- mov ah,2 ;vyvodim ego na ekran
- int 21h
- dec di ;umenshaem schetchik cifr
- jnz print ;esli di<>0 (ZF=0), to perehod na metku print
- ;i povtoraem pechat' simvola
- ret ;vyhod iz procedury
- prints endp
- InputInt proc
- INPUT: ; vvod chisla s klaviaturi
- mov ah,0ah
- xor di,di
- mov dx,offset buff ; adres bufera
- int 21h ; prinimaem stroku
- mov dl,0ah
- mov ah,02
- int 21h ; vivodim perevodya stroku
- ; obrabativaem bufer
- mov si,offset buff+2 ; berem adres nacala stroki
- cmp byte ptr [si],"-" ; esli perviy simvol -
- jnz ii1
- mov di,1 ; ustanavlivaem flag
- inc si ; i propuskaem
- ii1:
- xor ax,ax
- mov bx,10 ; osnovanie
- ii2:
- mov cl,[si] ; berem simvol is bufera
- cmp cl,0dh ; provaryaem ne posledniy li on
- jz endin
- ; esli ne posledniy ti proveryaem na pravilnost
- cmp cl,'0' ; esli vvedenniy simvol <0
- jb er
- cmp cl,'9' ; esli vvedenniy simvol >9
- ja er
- sub cl,'0' ; perevodim v chislo
- mul bx ; umnojaem na 10
- add ax,cx ; dobavlyaem k ostalnim
- inc si ; ukazatel na sleduyushiy simvol
- jmp ii2 ; povtoryaem
- er: ; esli bila oshibka to soobshaem i vihodim
- mov dx, offset error
- mov ah,09
- int 21h
- int 20h
- ; vse simvoli obrabotani chislo nahoditsya v ax
- endin:
- cmp di,1 ; esli ustanovlen flag to
- jnz ii3
- neg ax ; delaem chislo otricatelnim
- ii3:
- ret
- InputInt endp
- main: ;tochka vhoda v programmu
- mov ax,@data ;zanesenie adresa segmenta dannyh v ax
- mov ds,ax ;kopiruem ax v ds
- mov dx,10
- outmsg Mess1
- call InputInt
- mov bp,ax
- outmsg Mess2
- call InputInt
- xor bx,bx
- mov bx,ax
- call calc
- call prints
- jmp exit
- exit:
- lea dx,Exit_Mess ;v dx zanosim smeschenie Exit_Mess
- mov ah,09h ;v ah zanosim 9 funkciju DOS
- int 21h ;vyzov preryvanija 21h
- ;ozhidanie nazhatija klavishi
- mov ah,00h ;v ah zanosim funkciju 00h
- int 16h ;vyzov preryvanija 16h
- ;vyhod iz programmy
- mov ah,4ch ;v ah zanosim funkciju 4Ch DOS
- int 21h ;vyzov preryvanija 21h
- end main ;konec programmy main
Объяснение кода листинга программы
- На строке 5 объявляется модель памяти
small
. - На строках 7-12 объявляются макросы outmsg, который выводит сообщение на экран, соответствующие строки Mess1, Mess2 и Exit_Mess.
- На строке 14 объявляется стек размером 256 байт.
- На строке 16 объявляется сегмент данных.
- На строках 18-25 объявляется переменная
error
со значениемincorrect number
. - На строке 26 объявляется переменная
buff
как массив из 6 элементов. - На строке 31 начинается процедура
calc
, которая вычисляет результат логического побитового исключающего ИЛИ.- Значение переменной B передается через регистр bx.
- Значение переменной A передается через регистр bp.
- Результат вычислений сохраняется в регистре ax.
- На строке 61 начинается процедура
prints
, которая выводит число из регистра ax на экран. - На строке 107 начинается процедура
InputInt
, которая считывает число с клавиатуры. - На строке 171 начинается основная программа
main
:- Сначала вводится число A с помощью вызова процедуры
InputInt
и сохраняется в регистре bp. - Затем вводится число B с помощью вызова процедуры
InputInt
и сохраняется в регистре bx. - Затем вызывается процедура
calc
для вычисления результата логического побитового исключающего ИЛИ и результат сохраняется в регистре ax. - Затем вызывается процедура
prints
для вывода результата на экран. - Наконец, программа завершается с выводом сообщения
Nazhmite lubuju klavishu...
и ожиданием нажатия клавиши.
- Сначала вводится число A с помощью вызова процедуры
- Программа завершается с вызовом прерывания 4Ch для выхода из программы.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д