简体   繁体   中英

Calculate an equation with given values and divide/multiply the result depending on whether it's odd or even

So I have this equation and these values:

x = (-53/a + d - 4 * a)/(1 + a * b);

а = {53, -1, -53, -1, -1};
b = {6, 11, -1, 5, -2};
d = {851, 3, -159, -73, -99}

I have to write a program that already has these values and just solves the equation 5 times, so like for the first time a is 53, b is 6, d is 851 and just do basic calculating. Then if the answer is even it should be divided by 2, and if it's odd it should be multiplied by 5.
The OBJ and EXE files get created without any problems but the calculations are very odd. I'm pretty sure I messed up the data in the registers because I can see that like in the 3rd equation what had to be the a value got the value from d and similar things probably happen to other variables as well, but I just don't see where in the code it starts to mess up. Can someone help me please?

.386
option casemap :none
include d:\masm32\include\masm32rt.inc

.data
    header DB 'Lab work', 0
    variant DB '(-53/a + d - 4*a)/(1 + a*b)', 13, 13, 0
    
    results DB 'if a = %d, b = %d, d = %d: ', 13, 'Result before modification: %d', 13,
    'Result after modification: %d', 13, 13, 0
    zeroDivision DB "Set %d", 13 , "(-53/(%d) + (%d) - 4 * (%d))/(1 + (%d) * (%d)) = %d/%d", 13,
    "Zero division!", 13, 13, 0
    
    Avals DD 53, -1, -53, -1, -1
    Bvals DD 6, 11, -1, 5, -2
    Dvals DD 851, 3, -159, -73, -99
    
    numerator DD 0
    denominator DD 0
    
    result1 DD 5 DUP(?)
    result2 DD 5 DUP(?)
    
    buff DB 256 DUP(?)
    fOutput DB 512 DUP(?)
    
    .code
    
    start:
        
        mov edi, 0
        
        invoke wsprintf, addr fOutput, addr variant
        
        .WHILE edi < 5
        calculating:
            mov eax, Avals[4 * edi] ;values of A in eax
            cmp eax, 0
            je error_0 
            
            mov ecx, -53 
            cdq
            idiv eax ;-53/a in ecx
            
            mov edx, 4
            imul edx, eax ;4*a in edx
            
            mov ebx, Bvals[4 * edi]
            imul eax, ebx ;a*b in eax
            
            inc eax ;1 + a*b in eax
            
            cmp eax, 0
            je error_0
            mov denominator, eax
            
            mov eax, Dvals[4 * edi] 
            add ecx, eax ;-53/a + d in ecx
            
            sub ecx, edx ; -53/a + d - 4*a in ecx
            mov numerator, ecx
            cdq
            idiv denominator ;(-53/a + d - 4*a) / (1 + a*b) in eax
            
            mov result1[4 * edi], eax ;result1 
            
            test eax, 1 ;checking result1 whether it's odd or even 
            jnz odd     ;if odd - multiply by 5, if even - divide by 2
                mov esi, 2
                cdq
                idiv esi
                jmp outif
            odd:
                imul eax, 5
            outif:
            
            mov result2[4*edi], eax 
            invoke wsprintf, addr buff, addr results, Avals[4*edi], Bvals[4*edi], Dvals[4*edi], result1[4*edi], result2[4*edi]
            jmp cont
            error_0:
            invoke wsprintf, addr buff, addr zeroDivision, Avals[4*edi], Bvals[4*edi], Dvals[4*edi]
            jmp cont
            cont:
            invoke szCatStr, addr fOutput, addr buff
            inc edi 
        .ENDW
        
        invoke MessageBox, 0, addr fOutput, addr header, 0
end start
calculating: mov eax, Avals[4 * edi];values of A in eax cmp eax, 0 je error_0 mov ecx, -53 cdq idiv eax;-53/a in ecx

The dword-sized division always divides the value in EDX:EAX by the value in the single operand that the instruction specifies. Your code is doing it the other way round!

mov  ecx, Avals[4 * edi]
mov  eax, -53
cdq                       ; EDX:EAX = -53
idiv ecx                  ; EAX = (-53/a)

As a consequence the other calculations are also wrong.
Next code to help you on the way:

add  eax, Dvals[4 * edi]  ; EAX = (-53/a + d)

shl  ecx, 2
sub  eax, ecx             ; EAX = (-53/a + d - a*4)

Tip: don't try to load the a , b , and d variables in the corresponding EAX , EBX , and EDX registers. It might seem helpful, but trust me it doesn't...


 mov esi, 2 cdq idiv esi

When the result turned out even, you were tasked to divide by 2. You should never use an actual division for this. Just shift the value to the right.

sar  eax, 1

sar is "ShiftArithmeticRight". It preserves the sign of the value. ( shr would not preserve the sign!)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM