Samina Jabeen
Samina Jabeen

Reputation: 33

Incorrect calculation of mathematical equation in Assembly Language (Intel)

I have an equation that I want to model in Assembly language. I wrote the following code which is syntactically correct but producing wrong results in register. Final result is to be stored in DX register. The equation I am modeling is:

DX = (AX2 + (AX-1) + 2 * (AX+2)) / 2

Following is the code in assembly language for Intel microprocessor:

[org 0x0100]
            jmp start

number:         db  02
multiplicand:   db  0
multiplier:     db  0
multiResult:    dw  0
squareResult:   dd  0


square:     mov   [multiplicand], AX
            mov   [multiplier], AX
            call  multi
            mov   AX, [multiResult]
            mov   [squareResult], AX
            ret


multi:          mov CL, 8
                mov BX, [multiplicand]
                mov DX, [multiplier]

carryCheck:     shr BX, 1
                jnc skip

                 add    [multiResult], BX


skip:           shl BX, 1
                dec CL
                jnz carryCheck
                ret


start:          mov AX, [number]
                call    square
                mov DX, [squareResult]
                sub byte[number], 1
                add DX, AX
                add byte[number], 2
                mov AX, [number]
                mov [multiplicand],AX
                mov byte[multiplier], 2
                call    multi
                add DX, [multiResult]
                shr DX, 1                   ; division by 2

            mov AX, 0x4c00              ;ending program
            int 0x21

Upvotes: 1

Views: 273

Answers (2)

James Georgas
James Georgas

Reputation: 159

At the carryCheck: label, the instruction shr BX, 1 should be shr DX, 1.

Upvotes: 0

Peter Cordes
Peter Cordes

Reputation: 365147

You are making this way too complicated. First, simplify the expression to one that's easier to compute

(AX*AX + (AX-1) + 2 * (AX+2)) / 2;
(AX*AX + AX + 2*AX - 1 + 2) / 2
(AX*AX + 3*AX + 1) / 2
(AX*(AX+3) + 1) / 2

That's easy and straightforward to implement:

mov   dx, ax
add   dx, 3      ; dx = ax+3

mul   dx         ; dx:ax = ax * (ax+3)

inc   ax         ; ignore the high-half of the mul result in DX.
shr   ax, 1

mov   dx, ax     ; apparently you want the result in DX?

Or are you supposed to keep 32-bit temporaries? If so, use ADD/ADC to add 1 to DX:AX. If you're using emu8086 or something, then you can't use SHRD to shift a bit from DX into AX. So you could use SHR to shift a bit out of DX, and RCR to shift that bit into AX.

You'd also need to save the carry-out from AX+3 if you do it this way.


BTW, you can easily ask a compiler for ideas. gcc doesn't really do pure 16-bit, though, and with 32-bit unsigned compiling in 32-bit mode, it uses LEA in ways that 16-bit addressing modes don't support. But here's what I tried on Godbolt.


If you want to fix your original code, use a debugger. IDK why you're branching on anything, or using memory for anything, and there are no comments.

Upvotes: 1

Related Questions