Программа, решающая уравнение в сборке
У меня проблема с моей простой программой в сборке. Я использую DOSbox и TASM . У меня проблема с программой. Типы операндов не совпадают в строке 76 78 80 . Это уже после умножения. Я попытался внести некоторые изменения, используя переменную difftrent size
; --------------------------------------------
; Equation=(a+c*b)/d-2*c,
; --------------------------------------------
.model small
.stack 100h
.data
a db 0
b db 0
c db 0
d db 0
result1 db ?
result2 db ?
message1 db "Equation: (a+c*b)/d-2*c a=$"
message2 db "b=$"
message3 db "c=$"
message4 db "d=$"
message5 db "Result=$"
.code
start: mov ax,@data
mov ds,ax
mov ax, seg message1 ;get a and save to a variable
mov ds,ax
mov dx,offset message1
mov ah, 9h
int 21h
mov ah, 1h
int 21h
sub al,30h ;converting to real number
mov a,al
mov ax, seg message2 ;get b and save to a variable
mov ds,ax
mov dx,offset message2
mov ah, 9h
int 21h
mov ah, 1h
int 21h
sub al,30h ;converting to real number
mov b,al
mov ax, seg message3 ;get c and save to a variable
mov ds,ax
mov dx,offset message3
mov ah, 9h
int 21h
mov ah, 1h
int 21h
sub al,30h ;converting to real number
mov c,al
mov ax, seg message4 ;get d and save to a variable
mov ds,ax
mov dx,offset message4
mov ah, 9h
int 21h
mov ah, 1h
int 21h
sub al,30h ;converting to real number
mov d,al
mov al,b ; (a+c*b) ------------------------error
mul c
add ax,a ; ------------------------error
push ax ;save current ax
mov ax,c ;d-2*c------------------------error
shl ax,2
sub d,ax
pop bx ;get previous ax to bx
div bx ; div ax:bx
mov result1,al
mov result2,ah
add result1,30h ;converting to string
add result2,30h ;converting to string
mov al,result1
mov bl,result2
mov ax, seg message5
mov ds,ax
mov dx,offset message5
mov ah, 9h
int 21h
mov al,result1
mov bl,result2
mov dl, al
mov ah , 2h
int 21h
mov dl, bl
mov ah , 2h
int 21h
mov ax,4C00h
int 21h
end start
1 ответ:
Ваша программа почти хороша, у вас есть только некоторые проблемы с размерами операндов, что нормально. Поэтому я взял ваш код и внес некоторые небольшие изменения, эти изменения прокомментированы и отмечены стрелками (
- Исправлена проблема размера операнда. Я все еще использую DB, потому что заметил, что вы записываете числа как одиночные символы.
- результат (d-2*c) сохраняется в BX. Это потому, что нам нужно разделить (a+c*b) / (d-2*c), и вы выскакивали (a+c*b) в BX, Итак, когда вы делаете
div bx
, вы делали (d-2*c) / (a+c*b).- разделил отображение на частное и остаток.
- добавлены
13,10
разрывы строк в сообщениях.- исправлено
Остаток получается изshl ax,2
поshl ax,1
. Одинshl
- x2, дваshl
- x2x2.dl
, потому что когдаdiv
использует слово в качестве делителя, остаток остается вdx
.Вот ваш код с небольшими изменениями (протестирован на EMU8086):
; -------------------------------------------- ; Equation=(a+c*b)/d-2*c, ; --------------------------------------------.model small .stack 100h .data a db 0 b db 0 c db 0 d db 0 result1 db ? result2 db ? message1 db 13,10,"Equation: (a+c*b)/d-2*c",13,10,"a=$" message2 db 13,10,"b=$" ;<================= 13,10 IS message3 db 13,10,"c=$" ;<================= LINEBREAK. message4 db 13,10,"d=$" ;<================= message5 db 13,10,"Quotient=$" ;<================= message6 db 13,10,"Remainder=$" ;<================= .code start: mov ax,@data mov ds,ax mov ax, seg message1 ;get a and save to a variable mov ds,ax mov dx,offset message1 mov ah, 9h int 21h mov ah, 1h int 21h sub al,30h ;converting to real number mov a,al mov ax, seg message2 ;get b and save to a variable mov ds,ax mov dx,offset message2 mov ah, 9h int 21h mov ah, 1h int 21h sub al,30h ;converting to real number mov b,al mov ax, seg message3 ;get c and save to a variable mov ds,ax mov dx,offset message3 mov ah, 9h int 21h mov ah, 1h int 21h sub al,30h ;converting to real number mov c,al mov ax, seg message4 ;get d and save to a variable mov ds,ax mov dx,offset message4 mov ah, 9h int 21h mov ah, 1h int 21h sub al,30h ;converting to real number mov d,al mov al,b ; (a+c*b) mul c mov cl,A ;<======== MOV A TO CX TO mov ch,0 ;<======== ADD IT TO AX. add ax,CX ;<======== C*B + A. ;push ax ;<======== NO LONGER NECESSARY BECAUSE ;<======== IN NEXT BLOCK WE USE BX. mov bl,C ;<======== MOV C TO BL AND CLEAR mov bh,0 ;<======== BH. NOW C IS IN BX. shl bx,1 ;<======== 2*c. ONE SHIFT IS x2, TWO SHIFTS ARE x2x2. sub d,bl ;d - 2c mov bl,d ;<======== MOV D TO BL AND CLEAR BH. NOW mov bh,0 ;<======== D IS IN BX. BX = (D-2C). ;pop ax ;<======== NO LONGER NECESSARY. AX CONTAINS (A+C*B). mov dx,0 ;<======== CLEAR DX, BECAUSE DIVISOR IS A WORD. ;<======== WHEN DIVISOR IS A WORD, DIV USES DX:AX. div bx ;<======== dx:ax / bx == DX:(A+C*B) / (D-2C). THIS ;<======== DIVISION IS UNSIGNED, FOR SIGNED USE IDIV. mov result1,al ;<===== QUOTIENT. mov result2,dl ;<===== REMAINDER, BECAUSE DIVISOR IS WORD. add result1,30h ;converting to string add result2,30h ;converting to string mov al,result1 mov bl,result2 ;DISPLAY QUOTIENT <============= mov ax, seg message5 mov ds,ax mov dx,offset message5 mov ah, 9h int 21h mov al,result1 mov dl, al mov ah , 2h int 21h ;DISPLAY REMAINDER <============= mov ax, seg message6 mov ds,ax mov dx,offset message6 mov ah, 9h int 21h mov dl, bl mov ah , 2h int 21h mov ax,4C00h int 21h end start
Далее идет ваше "делать" список:
Измените размер операндов с DB на DW, чтобы ваша программа могла обрабатывать большие числа.
- измените DIV на IDIV, потому что DIV не имеет знака, а IDIV подписан. IDIV позволит вам справиться с отрицательными результатами.
- захват чисел с int=21h ah=0Ah в виде строк (не в виде одиночных символов). Позже вы преобразуете строки в числа. Следующие две ссылки приведут вас к процедурам преобразования строки в число:
Дата сборки x86 до Number-разбиение строки на более мелкие части
32 разрядный калькулятор в сборке 8086
Наконец, данные испытаний:
(a+c*b) / (d-2*c) a=1 b=2 c=3 d=8 a+c*b = 1+3*2 = 7 d-2*c = 8-2*3 = 2 7 / 2 = quotient 3, remainder 1