I\'m computing the average of 3 marks:
g0 dw 70
g1 dw 100
g2 dw 65
with
xor rax, rax
xor rcx, rcx
mov ax, [g0]
inc rc
You can change the variables to bytes if you use another register for the adding. So the following is possible:
g0 db 70
g1 db 100
g2 db 65
Use the MOVZX instruction and indicate the memory reference size BYTE:
xor ecx, ecx ; clear counter register and break dependencies
movzx eax, BYTE [g0] ; movzx loads g0 and fills the upper bytes with zeroes
inc ecx
movzx edx, BYTE [g1] ; move byte from g1 to dl and zero-extend
add eax, edx ; add the widened integers
inc ecx
movzx edx, BYTE [g2] ; the upper half of RDX is zeroed automatically by this instruction, but 32-bit is fine.
add eax, edx
inc ecx
xor edx, edx
div ecx ; unsigned division of EAX / 3
; quotient in EAX, remainder in EDX
;mov [average], al ; or do whatever you want with it.
There's also no need to use 64-bit operand size. 32-bit is the "standard" operand-size for x86-64 for most instructions.
Of course, you can change the eax
and edx
register references to rax
and rdx
, respectively, because the values have been zero-extended to the full register width. If you had more than 2^32 / 100
grades to add, you could use that to avoid overflow.
If you're repeating this a fixed number of times, mov ecx, count
instead of using that many inc
instructions. inc
would make sense if this was in a loop body and you were incrementing a pointer to an array of grades, but part of the benefit of fully unrolling is not having to inc
anything to count interations.