代码之家  ›  专栏  ›  技术社区  ›  user3408267

为什么我会溢出?(NASM汇编程序)

  •  1
  • user3408267  · 技术社区  · 9 年前

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

    所以我开发的这段代码适用于所有变量,这些变量相乘后不会导致EDX寄存器被填充。我不能将寄存器移位或“或”,也不能使用跳转或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 回复  |  直到 9 年前
        1
  •  0
  •   Sep Roland    9 年前

    让我们浏览整个计算过程:

    mul   al               ;obtain r^2
    

    mul al 在中留下结果 AX 登记所以你必须在下一行使用单词multiple 否则你会失去 第^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