1

I am new to Assmbly language and I'm practicing for future use. I've tried a lot of ways, read a lot of articles and a lot of examples but I just can't compute the surface area properly also the output is not the output I wanted. Here's my code. The formula for surface area of Polygon is S = (2 × Base Area) + (Base perimeter × height)

data segment
string0 db 10,13,'SURFACE AREA OF POLYGON CALCULATOR$'
string1 db 10,13,'ENTER BASE AREA OF POLYGON: $'
string2 db 10,13,'ENTER HEIGHT OF POLYGON: $'
string02 db 10,13,'ENTER BASE PERIMETER OF POLYGON: $'
string3 db 10,13,'RESULT: $'

val1 db ?
base db ?
height db ?
perimeter db ?
BaseArea db ?
ends

code segment
    assume ds:data, cs:code
start:
    mov ax,data        ; mov data to register
    mov ds,ax  
    
    lea dx,string0      ;display data on data segment
    mov ah,9
    int 21h
    
    lea dx, string1      ;display data on data segment
    mov ah, 9
    int 21h
    
    mov ah,01h           ;user input
    int 21h
    sub al,'0'
    mov val1,al           
    mov base,al            ;move al->base
    aam 
    add ah,30h
    add al,30h
    mov bx,ax
   
    lea dx, string2
    mov ah, 9
    int 21h
    
    mov ah,01h
    int 21h
    
    sub al,'0'
    mov height,al              ;move al->hgt(height) for multiplication
    mul base                ;multiply hgt x base
    mov res,al              ; move al,res
    aam
    add ah,30h
    add al,30h
    mov bx,ax
    
    mov al,sqr              ;move stored data in sqr->al for addition
    add res,al               ;add al + res
    aaa
    add ah,30h
    add al,30h
    mov bx,ax

    lea dx, string3             ;display string
    mov ah,9
    int 21h

    add dl,'0'
    
    mov ah,2
    mov dl,bh
    int 21h
    
    add dl,'0'
    mov ah,2
    mov dl,bl
    int 21h
    
    add dx,'0'
    mov ah,2
    mov dx,bx
    int 21h
    
    mov ah, 4ch
    int 21h


ends
end start
sample input: 6,3
output: >C
  • The most visible problem seems to be [Displaying numbers with DOS](https://stackoverflow.com/q/45904075) - you're using `aam` to divide by 10 once, which works for 2-digit numbers, but it seems you have a 3-digit output where one of the digits comes out as `a`. – Peter Cordes Apr 04 '22 at 10:51
  • With 2 two multiplies in a row, I wouldn't be surprised if you overflow an 8-bit integer; you're only saving the low 8 bits, and you're calling it sqrt (square *root*?) even though you haven't taken a square root. Also, this would be a better question if you showed the formula you're trying to evaluate, so readers don't have to go look up the area formula themselves. – Peter Cordes Apr 04 '22 at 10:53
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/243603/discussion-on-question-by-asjsjs-computing-surface-area-of-a-polygon-printing). – Ryan M Apr 05 '22 at 04:05

1 Answers1

2
tst db '5'
side db '6'

The use of the single quotation marks turned these numbers into characters!
Your program was erroneously multiplying with 53 and 54.


You are doing too many things at once! There's inputting, calculating, and outputting that you are mixing to the extent that you are losing track.

Inputting

Your program needs 2 numbers from the user: the radius and the height. There's little benefit from inputting the radius twice. That's a source for mistakes.
The procedure is as follows:

  • Display an inviting prompt
  • Wait for a single keyboard key
  • Convert the key from character "1" to "9" to digit 1 to 9
  • Store in a variable with a descriptive name

Repeat the above for both inputs and of course storing into separate variables. Radius and Height will be the only variables that remain in your program.

Calculating

In calculations there's always the risk of numerical overflow. You have to find out what's going to be the worst case that you can expect. In this program it's a radius=9 and a height=9. Use a calculator and see that the surface would be 891. That's not going to fit in just 8 bits, but it does not necessarily mean that we will have to upscale the calculation to 16 bits. We can rearrange the expression so that only the final step will produce a 16-bit value.

    6 * Radius * Height + sqrt(27) * Radius^2
<=> Radius * (6 * Height + sqrt(27) * Radius)

Next 7 instructions is all it takes:

mov al, 6
mul Height    ; -> AL is at most 54
mov bl, al
mov al, 5     ; Truncated for simplicity: sqrt(27) = 5.196...
mul Radius    ; -> AL is at most 45
add al, bl    ; -> AL is at most 99
mul Radius    ; -> AX is at most 891

Outputting

Since the final result could have 3 digits, using aam is not gonna cut it. I have prepared a very nice explanation (if I dare say so myself) about displaying numbers in DOS.
You will want to display an accompanying message. Make sure that you don't corrupt the value in AX that the above computation gave you!

The procedure is as follows:

  • Put AX on the stack using push ax
  • Display the message
  • Get AX back using pop ax
  • Display the number in AX using the code from the link

I'm practicing for future use

Keep doing this, you have my support.


Extra : want some more accuracy?

In the above code, that sqrt(27) was truncated for simplicity at the expense of accuracy. It is however possible to increase the accuracy and still only use integer arithmetic.
The outcome of the calculation will not change if we multiply by 1000 and then divide by 1000. It is rearranging the expression that will allow to use 5.196 * 1000 = 5196 in the integer calculation.

    6 * Radius * Height + sqrt(27) * Radius^2
<=> (6 * Radius * Height + sqrt(27) * Radius * Radius) * 1000 / 1000
<=> (1000 * 6 * Radius * Height + 1000 * sqrt(27) * Radius * Radius) / 1000
<=> (6000 * Radius * Height + 5196 * Radius * Radius) / 1000

Make sure that Radius and Height are defined as word-sized variables this time:

mov ax, 6000
mul Radius    ; -> DX:AX is at most 54000
mul Height    ; -> DX:AX is at most 486000

mov bx, ax    ; -> CX:BX = DX:AX
mov cx, dx

mov ax, 5196
mul Radius    ; -> DX:AX is at most 46764
mul Radius    ; -> DX:AX is at most 420876

add ax, bx    ; -> DX:AX is at most 906876
adc dx, cx

mov bx, 1000
div bx        ; -> AX is at most 906

mov bx, 499   ; Round to nearest
sub bx, dx    ; DX is remainder [0,999]
adc ax, 0     ; -> AX is at most 907
Sep Roland
  • 33,889
  • 7
  • 43
  • 76