Write a MARIE assembly language program that calculates and displays the perimet
ID: 672486 • Letter: W
Question
Write a MARIE assembly language program that calculates and displays the perimeter or the area of a rectangle, given the length of each side, depending on the user’s input.
The user should be prompted to enter the length of each of the sides; once these values have been read by the program, provide the user with the options to select which calculation to perform on the rectangle, and prompt them to enter one of the options.
For example: Enter Perimeter(P) or Area(A)
The application should accept a character corresponding to one of the actions: P for Perimeter or A for Area. The output statements should accurately describe the results being displayed. For example, if the input is:
4 (for one side)
5 (for the other side)
A (for calculation type)
Your program should print something like this: The area of the rectangle is 20.
Explanation / Answer
Solution :
.data
;The limit for each dimension is 2 digits (max 99*99) because otherwise the answer might be too big for the 16 register to hold
msg byte 0dh, 0ah, 0dh, 0ah, "Demonisch Rectangle area calculator", 0dh, 0ah, "Each dimension can be up to two digits long", 0dh, 0ah, "$"
msgWid byte 0dh, 0ah, "Width: $"
msgHei byte 0dh, 0ah, "Height: $"
msgDim byte 0dh, 0ah, "The area of the rectangle is: $"
msgEnd byte 0dh, 0ah, 0dh, 0ah, "Press any key to continue", 0dh, 0ah, 0dh, 0ah, "$"
wid word 0000h
.code
main PROC
mov ax, SEG msg
mov ds, ax
mov ah, 9
mov dx, OFFSET msg ;Show header message
int 21h
getWid:
mov ah, 9
mov dx, OFFSET msgWid ;Ask for width
int 21h
call getNum ;Call function getNum(), returns entered num in bx
cmp bx, 0000h ;If an error occured getNum() returns 0, not a valid dimension so get another number
je getWid
mov wid, bx ;Store the width
getHei:
mov ah, 9
mov dx, OFFSET msgHei
int 21h
call getNum
cmp bx, 0000h
je getHei
mov ax, bx ;ax stores the height
mov cx, wid ;cx stores the width, which is used to know how many times to loop
mov bx, 0000h ;Reset bx to 0 so it can be added to
mulAns:
add bx, ax ;Keep adding the height to itself
dec cx
cmp cx, 0000h ;Until width is 0
jg mulAns
disAns:
mov ah, 9
mov dx, OFFSET msgDim
int 21h
call disNum
proEnd:
mov ah,9
mov dx,OFFSET msgEnd
int 21h
mov ah, 1 ;Wait for any key, allows the user to read any output
int 21h ;before the programme ends and the window closes
mov ah, 4ch
int 21h
main ENDP
;-----------------------------------------------------------------------------------
getNum PROC
.data
msgBN byte " [Only enter digits]$"
msgZ byte " [Zero number not allowed]$"
numIn word 0000h
.code
push ax ;This sub requires bx to pass the number back
push cx ;But everything else can be reserved
push dx
push si
push di
readNumS: ;Start
mov cx, 0000h
mov numIn, 0000h ;Reset the values, otherwise repeated calls to this function will use the last stored values
readNumG: ;Get
mov ah, 8 ;Silent read mode, does not echo to the screen
int 21h
mov bx, 0000h
mov bl, al
cmp bl, 0Dh ;Return
je readNumF
cmp bl, 30h ;0 (ASCII 48)
jl badNum
cmp bl, 39h ;9 (ASCII 57)
jg badNum
mov ah, 6 ;Char display mode
mov dl, bl
int 21h ;Display the entered char
sub bl, 30h ;Turn into digit
mov dx, numIn
mov ax, dx
mov ch, 00h
readNumL: ;Loop ten times, moving all the digits in the current numIn 1 place forward (effectively * 10)
add ax, dx
inc ch
cmp ch, 09h
jl readNumL
add ax, bx
mov numIn, ax
inc cl
cmp cl, 02h ;Only allow 2 digit numbers
jl readNumG
readNumF:
cmp numIn, 0000h ;Do not accept the number 0
je zeroNum
mov bx, numIn
readNumE:
pop di ;Returns all of the registers apart from bx to there original states
pop si
pop dx
pop cx
pop ax
ret
;Errors
zeroNum:
mov ah, 9
mov dx, OFFSET msgZ
int 21h
mov bx, 0000h
jmp readNumE
badNum: ;Digit was expected but not entered
mov ah, 6 ;Display the offending character
mov dl, al
int 21h
mov ah, 9
mov dx, OFFSET msgBN
int 21h
mov bx, 0000h
jmp readNumE
getNum ENDP
;--------------------------------------------------------------------------------;
disNum PROC
.data
numOut word 0000h
.code
mov numOut, bx ;Store a copy before pushing, so the original after this method stays the same
push ax
push bx
push cx
push dx
push si
push di
mov bx, numOut ;Use this copy
disNumF:
mov cl, 00h
cmp bx, 03E8h ; 1000
jge getThou
cmp bx, 0064h ; 100
jge getHun
cmp bx, 000Ah ; 10
jge getTen
jmp disUnit
getThou:
inc cl
sub bx, 3E8h
cmp bx, 3E8h
jge getThou
disThou:
add cl, 30h
mov ah, 6
mov dl, cl
int 21h
mov dl, 2Ch ;Display thousand comma
int 21h
mov cl, 00h
cmp bx, 64h
jl disHun
getHun:
inc cl
sub bx, 64h
cmp bx, 64h
jge getHun
disHun:
add cl, 30h
mov ah, 6
mov dl, cl
int 21h
mov cl, 00h
cmp bx, 0Ah
jl disTen
getTen:
inc cl
sub bx, 0Ah
cmp bx, 0Ah
jge getTen
disTen:
add cl, 30h
mov ah, 6
mov dl, cl
int 21h
mov cl, 00h
cmp bx, 01h
jl disUnit
disUnit:
add bl, 30h
mov ah, 6
mov dl, bl
int 21h
pop di ;Restore previous values, most importantly bx in case the user wants to use that number again
pop si
pop dx
pop cx
pop bx
pop ax
ret
disNum ENDP
;--------------------------------------------------------------------------------;
END main
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.