我为什么要溢出? (NASM汇编)

时间:2016-02-09 06:58:48

标签: assembly nasm integer-overflow irvine32

为了这个程序,我必须制作一个程序来计算一个22/21 *(r ^ 2)* h的圆锥体积。

因此,我开发的这段代码适用于任何不会导致EDX寄存器在将变量相乘后填充的变量。我无法移动寄存器或" OR"他们在一起,我也不能使用跳转或cmp语句。我还必须使用8位寄存器作为高度和宽度变量,16位用于半径^ 2和半径^ 2 *高度计算,然后用32位完成它以进行最终除法计算。看一看。我不知道为什么它会溢出到EDX而且我不知道如何纠正它...

.data

radius          WORD ?                                      ;var for radius
height          WORD ?                                      ;var for height
numerator       WORD 22                                     ;Making a variable for numerator
denominator     DWORD 21                                    ;Making a variable for denominator
volume          DWORD ?                                     ;Making a variable to store volume main
decimal         DWORD ?                                     ;Making a variable to store volume remainder
prompt BYTE "Enter the radius: ",0                          ;val for radius prompt
promp2 BYTE "Enter the height: ",0                          ;val for height prompt
result BYTE "The volume of the cone is: ", 0                ;val for printing volume
decim  BYTE ".", 0                                          ;val for decimal place

                                                                ;volume of cone is 1/3(pi(r^2)h) or 22/21(r^2)h

.code

main PROC
    mov edx,OFFSET promp2                                       ;move prompt into edx for printing
    call WriteString                                            ;ask user for height

    mov eax,0
    mov edx,0
    mov ecx,0
    mov ebx,0                                                   ;move zero into all main registers

    call ReadDec                                                ;reading the height
    mov bl,al                                                   ;move height into storage

    mov edx,OFFSET prompt                                       ;move promp2 into edx for printing
    mov eax,0                                                   ;re-zero eax
    call WriteString                                            ;ask user for radius
    call ReadDec

    mul al                                                      ;obtain r^2
    mul bl                                                      ;multiply r^2 by height
    mov edx,0                                                   ;zero out edx
    mov dx,numerator                                            ;move numerator into dx
    mul dx                                                      ;multiply r^2*h by 22

    mov ebx,denominator                                         ;move 21 into ebx to divide
    div ebx                                                     ;divide by 21 to get total volume
    mov volume,eax                                              ;move volume into volume variable
    mov decimal,edx                                             ;move decimal remainder into decimal variable

    mov edx,OFFSET result                                       ;prepare string result for printing
    call WriteString                                            ;print result string
    mov eax,volume                                              ;move volume into eax to print     
    call WriteDec                                               ;print volume
    mov edx,OFFSET decim                                        ;move dec into print register
    call WriteString                                            ;print decimal
    mov eax,decimal                                             ;move decimal remainder into eax to print
    call WriteDec                                               ;print decimal value
    call CRLF                                                   ;carriage return and new line
    call WaitMsg                                                ;pause output

    exit
main ENDP

也许我可以为中间算术做不同的寄存器,但我不知道如何在目前的8-8-16-16-32要求下完成。如果有人可以帮助我找到一个有效的解决方案,并解释它为什么会起作用,也许可以逐步完成它,这样我就能理解为什么我的工作不适用于更大的整数(大多数超过20个不工作),这将是惊人的。提前感谢您提供给我的任何帮助!

1 个答案:

答案 0 :(得分:0)

让我们来看看整个计算:

mul   al               ;obtain r^2

mul al会将结果留在AX注册表中。因此,您必须在下一行中使用单词乘法,否则您将丢失 r ^ 2 的部分值。

mov   bh, 0
mul   bx               ;multiply r^2 by height

现在结果在DX:AX。要将它乘以22,您可以通过堆栈将其移动到32位寄存器EAX

push  dx
push  ax
pop   eax
movzx edx, numerator   ;Why is this defined a word?
mul   edx

这次结果在EDX:EAX,准备进行最后的分工。

div   denominator

最后将EAX中的商和EDX中的余数移到各自的变量中。

mov   volume, eax      ;move volume into volume variable
mov   decimal, edx