使用宏在 MASM 中划分数字?
Dividing numbers in MASM using macros?
我正在尝试编写一个 MASM 宏,它接受一个数字并将其除以二:
mCalculateDiscount MACRO originalPrice
PUSH EDX
PUSH ECX
MOV EDX, 0
MOV EAX, originalPrice
MOV ECX, 2
DIV ECX
POP ECX
POP EDX
ENDM
而且答案会保存在 EAX 里面,这种方法是错误的,哪种方法是正确的,使用宏还是过程?
对于真正归结为单个指令的操作(不算加载操作数的代码),我认为您通常会直接编写它,而无需诉诸宏。
像这样的宏是低效的,因为它没有考虑周围的代码。如果您在 EDX 中没有任何重要数据怎么办?那么EDX的push/pop就浪费了。 ECX 也是如此。或者也许在您周围的代码中,ECX 用于其他用途,但 ESI 可用;如果直接编码,您可以只使用 ESI 作为除数。使用宏你就失去了这个机会。
如果你的代码变得如此复杂,以至于没有像这样的宏你就无法保持组织有序,那么可能是时候将它移植到像 C 这样的高级语言了。你的内置宏 push/pop 正在做寄存器分配的弱版本,实际的编译器可以更有效地完成它。
最后,正如 Erik Eidt 指出的那样,使用 DIV 除以二效率非常低;您应该改为右移(可能快 10 倍左右),并且还可以避免需要一堆额外的寄存器。整个宏可以替换为
MOV EAX, originalPrice
SHR EAX, 1
我正在尝试编写一个 MASM 宏,它接受一个数字并将其除以二:
mCalculateDiscount MACRO originalPrice
PUSH EDX
PUSH ECX
MOV EDX, 0
MOV EAX, originalPrice
MOV ECX, 2
DIV ECX
POP ECX
POP EDX
ENDM
而且答案会保存在 EAX 里面,这种方法是错误的,哪种方法是正确的,使用宏还是过程?
对于真正归结为单个指令的操作(不算加载操作数的代码),我认为您通常会直接编写它,而无需诉诸宏。
像这样的宏是低效的,因为它没有考虑周围的代码。如果您在 EDX 中没有任何重要数据怎么办?那么EDX的push/pop就浪费了。 ECX 也是如此。或者也许在您周围的代码中,ECX 用于其他用途,但 ESI 可用;如果直接编码,您可以只使用 ESI 作为除数。使用宏你就失去了这个机会。
如果你的代码变得如此复杂,以至于没有像这样的宏你就无法保持组织有序,那么可能是时候将它移植到像 C 这样的高级语言了。你的内置宏 push/pop 正在做寄存器分配的弱版本,实际的编译器可以更有效地完成它。
最后,正如 Erik Eidt 指出的那样,使用 DIV 除以二效率非常低;您应该改为右移(可能快 10 倍左右),并且还可以避免需要一堆额外的寄存器。整个宏可以替换为
MOV EAX, originalPrice
SHR EAX, 1