Home > database >  Calculating using Assembly with signed values
Calculating using Assembly with signed values

Time:12-17

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.

  • Related