Your program is almost good, you only have some problems with the size of the operands, which is normal. So I took your code and made some small changes, these changes are commented and indicated by arrows (<========), and they are:
- Fixed problem with the size of the operand. I am still using the database because I noticed that you are fixing numbers as separate characters.
- The result (d-2 * c) is stored in BX. This is because we need to split (a + c * b) / (d-2 * c) and you popped (a + c * b) into BX, so when you make
div bx you did (d -2 * c) / (a ββ+ c * b). - Separate the display for private and rest.
- Added
13,10 line breaks in messages. - Fixed
shl ax,2 on shl ax,1 . One shl is x2, two shl is x2x2. - The rest is derived from
dl , because when the div uses the word as a divisor, the remainder remains in dx .
Here is your code with slight modifications (tested on 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
Next is your do list:
- Resize operands from DB to DW so that your program can handle large numbers.
- Change the DIV to IDIV, because the DIV is unsigned, while the IDIV is signed. IDIV will allow you to handle negative results.
- Capturing numbers with int = 21h ah = 0Ah as strings (not as separate characters). Later you convert strings to numbers. The following two links will lead you to string-to-number conversion procedures:
Assembly x86 Date to Number - break a string into smaller sections
32-bit calculator in assembly 8086
Finally, the test data:
(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