So for the question below:
Suppose x, y, and z are declared as quadwords and contain signed values. Write the assembly code that calculates the result of the following expression and leaves the result in the EAX register.
(x y) / (y / z)
has to be done with NASM x86-64, and I wanted to make sure if this logical instruction would make sense for the question above. It says leaving the result in EAX so I figured everything has to be done by E registers. If anyone could double-check, let me know, or if there are things to fix/improve.
And one other thing, it doesn't need to be a full-fleshed-out code. I already have all the declarations and functions outside this short segment of the instructional logic code so just assume I already have them defined.
mov ecx, [x]
mov edx, [y]
mov esi, [z]
;MATH
add ecx, edx ; (x y)
cdq ; 32 byte register
mov eax, edx
idiv esi ; (y/z)
mov edx, eax
mov eax, ecx ; (x y) into eax
cdq
idiv ecx ; (x y)/z
CodePudding user response:
Could you clarify through visual representation? I changed the declaration to ecx
from edx
, and fixed cdq
. I'm still not sure how to go about transitioning R registers and placing the result into EAX
mov ebx,[x] ; ebx = x
mov ecx,[y] ; ecx = y
mov esi,[z] ; esi = z
add ebx,ecx ; ebx = (x y)
mov eax,ecx ; eax = y
cdq ; edx:eax = y
idiv esi ; eax = (y/z) ; edx = remainder
mov ecx,eax ; ecx = (y/z)
mov eax,ebx ; eax = (x y)
cdq ; edx:eax = (x y)
idiv ecx ; eax = (x y) / (y/z)
CodePudding user response:
Commenting each instruction with the expected effect will help:
mov ecx, [x] ; ecx = x
mov edx, [y] ; edx = y
mov esi, [z] ; esi = z
;MATH ; eax is undefined garbage!
add ecx, edx ; ecx = (x y)
cdq ; edx:eax = eax ; overwrites edx with 0 or -1
mov eax, edx ; eax = either 0 or -1
idiv esi ; eax = (garbage / z), edx = remainder of garbage
mov edx, eax ; edx = garbage
mov eax, ecx ; eax = (x y)
cdq ; edx:eax = (x y)
idiv ecx ; eax= (x y) / (x y) = 1, edx = remainder 0
As you can see, using edx
for holding values is not a good idea when division is required. Instructions idiv
or div
expect dividend in register-pair edx:eax
and they overwrite eax
with the result (quotient) and edx
with the remainder.
cdq
should be used to extend the signed value from eax
to the pair edx:eax
before each division.
Choose another register for the y value. As Nate mentioned, for quadword values you'll need 64bit registers. Instead of cdq
you'll need cdo
to sign-extend rax
to rdx:rax
. When the final result fits to 32 bits, you can leave it in eax
as is, but it's usual for 64bit function to return rax
.