问题描述
我正在计算 3 分的平均值:
I'm computing the average of 3 marks:
g0 dw 70
g1 dw 100
g2 dw 65
与
xor rax, rax
xor rcx, rcx
mov ax, [g0]
inc rcx
add ax, [g1]
inc rcx
add ax, [g2]
inc rcx
xor rdx, rdx
idiv rcx
成绩不需要是单词,因为对于平均值来说字节就足够了,但总和必须是一个单词以避免溢出(即使用此算法).
The grades don't need to be words, because bytes would be enough as for the average, but the sum must be a word to avoid overflow (with this algorithm, that is).
如何将成绩转换为字节?使用 db
是不够的,因为那样我必须将 ax
更改为 al
,但它最终会导致溢出.我不能指示 mov/add
只从 [g*]
获取一个字节,因为这会导致操作数大小不匹配.
How can I convert the grades to bytes? Using db
isn't enough, because then I would have to change ax
to al
, but it would cause an overflow at the end.I cannot instruct the mov/add
to only take a byte from [g*]
, as it would cause a mismatch in the operand sizes.
我正在使用 yasm.
I'm using yasm.
推荐答案
如果您使用另一个寄存器进行添加,您可以将变量更改为字节.所以以下是可能的:
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
使用MOVZX
指令并指明内存参考大小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.
也不需要使用 64 位操作数大小.32 位是标准"对于大多数指令,x86-64 的操作数大小.
There's also no need to use 64-bit operand size. 32-bit is the "standard" operand-size for x86-64 for most instructions.
当然,您可以将 eax
和 edx
寄存器引用分别更改为 rax
和 rdx
,因为这些值已经零扩展到整个寄存器宽度.如果您要添加超过 2^32/100
个成绩,您可以使用它来避免溢出.
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.
如果你重复这个固定次数,mov ecx, count
而不是使用那么多的 inc
指令.inc
如果这是在一个循环体中并且你增加了一个指向成绩数组的指针,那么 inc
会有意义,但是完全展开的部分好处是不必 inc
任何东西都可以算作互动.
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.
这篇关于平均字节数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!