# x / 2 + 100 * (a + b) - 3 / (c + d) + e * e in assembly

write an algorithm for: x / 2 + 100 * (a + b) - 3 / (c + d) + e * e knowing that: a, c - word, b, d - byte, e - doubleword, x - qword

    mov eax, dword [x]
mov edx, dword [x + 4] ; edx:eax = x
mov ebx, 2
idiv ebx ; eax = edx:eax / ebx = x / 2
mov ebx, eax ; save the result in ebx so we can do the other operations
mov al, [b]
cbw ; ax = b
add ax, [a] ; ax = a + b
mov dx, 100
imul dx ; dx:ax = ax * dx = 100 * (a + b)
push dx
push ax
pop eax ; 100 * (a + b)
add ebx, eax ; ebx = x / 2 + 100 * (a + b)
mov al, [d] ; al = d
cbw ; ax = d
add ax, word [c] ; ax = c + d
mov cx, ax ; cx = c + d
mov ax, 3
cwd
idiv cx ; ax = dx:ax / cx
cwd
push dx
push ax
pop eax ; eax = 3 / (c + d)
sub ebx, eax
mov eax, ebx
cdq ; edx:eax = x / 2 + 100 * (a + b) - 3 / (c + d)
mov ebx, eax
mov ecx, edx ; ecx:edx = x / 2 + 100 * (a + b) - 3 / (c + d)
mov eax, [e]
imul dword [e] ; edx:eax = e * e
mov dword [result + 0], eax
mov dword [result + 4], edx


did I make it unnecessarily complicated?

• "Is it correct?" That's a question for you to answer before posting here. If it is not doing what it is supposed to, it is offtopic here. So, is it correct? If yes, please remove that sentence as it may seem to imply that you don't know if your code works correctly, giving others a reason to vote to close your post... Oct 21, 2020 at 4:50
• I'm sorry! it works but I'm new to assembly language and I didn't know if it was legit Oct 21, 2020 at 4:52
• kk, that's fine, I actualy thought it will be the case, but I wanted to prevent any further confusion, thanks Oct 21, 2020 at 4:53
• What is the target platform ?
– Kate
Oct 21, 2020 at 20:46
• Note that the entire expression is undefined for c=-d. Oct 22, 2020 at 3:35

write an algorithm for: x / 2 + 100 * (a + b) - 3 / (c + d) + e * e

a, c - word,
b, d - byte,
e - doubleword,
x - qword


Because your biggest number is 64 bits (x is a qword), your final result will have to be 64 bits too!

Your first operation was to divide the qword in x by 2. You seem to expect that this result will fit in just a single dword because you've moved the quotient in the EBX register. You cannot make this assumption and worse the division could easily produce a divide exception if the quotient doesn't fit in 32 bits.
For the solution you should be aware that dividing by 2 is actually simply a shift to the right.

mov   ebx, [x]
mov   ebp, [x + 4] ; EBP:EBX is x
sar   ebp, 1
rcr   ebx, 1       ; EBP:EBX is x / 2


This means that you'll have to scale up the other calculations too in order to add them to EBP:EBX using:

add   ebx, ...


Because addition is associative, you can start by calculating the e * e part. You did not rearrange the expression and had to move around some more the registers in the end. Not a big deal, but nicer my way:

mov   eax, [e]
imul  eax


Then comes 100 * (a + b):

movsx eax, word [a]
movsx edx, byte [b]
add   eax, edx       ; eax = a + b
mov   edx, 100
imul  edx            ; edx:eax = 100 * (a + b)


I'll leave 3 / (c + d) to you...

... and finally the end will be:

sub   ebx, eax
sbb   ebp, edx
mov   [result + 0], ebx
mov   [result + 4], ebp


did I make it unnecessarily complicated?

• It was a bit hard to read your program because you didn't insert some blank lines between the different operations.

• You don't need to write a size tag (byte, word, dword) if the register involved already implies the size. In mov dword [result + 0], eax the dword tag is redundant.

• Best have the comments in the program aligned above each other.

• Reread carefully to avoid typos like in:

  mov ecx, edx ; ecx:edx = x / 2 + 100 * (a + b) - 3 / (c + d)


Should be ECX:EBX.

• To compute a square: once you've loaded the number in the register, you can multiply by that same register and not turn to the memory a second time like you did:

  mov   eax, [e]
imul  eax        ; Don't write "imul dword [e]"