在 x86 程序集中使用宏查找 3 个数的最小值
Finding the Min of 3 Numbers with a Macro in x86 Assembly
我编写了一个简单的宏,用于查找三个数字中的最小值。在当前状态下,只有当第一个或第三个参数是最小值而不是第二个时,宏才会起作用。我的循环或比较有什么我没有发现的问题吗?或者我应该做些什么不同的事情?任何建议或意见表示赞赏。
findMin MACRO arg1, arg2, arg3
mov eax, arg1
cmp eax, arg2 ; if eax is greater than arg2 swap
jg swap1
cmp eax, arg3 ; if eax is greater than arg3 swap
jg swap2
jmp endMac
swap1: xchg eax, arg2
swap2: xchg eax, arg3
endMac:
ENDM
用于查找 3 个数字的最小值的简化宏(最小值将在 EAX 寄存器中)
findMin MACRO arg1, arg2, arg3
LOCAL L2, L3
mov eax, arg1
cmp eax, arg2
jg l2
cmp eax, arg3
jg l3
jmp endMac
L2: xchg eax, arg2
cmp eax, arg3
jg L3
jmp endMac
L3: xchg eax, arg3
endMac:
ENDM
MASM宏功能非常强大。您可以验证参数的类型,甚至可以进行条件汇编。结合自 Intel P6 系列处理器 以来可用的条件移动 CMOVcc,您可以将程序优化为
min MACRO arg1:REQ, arg2:REQ, arg3:REQ
; Returns result in EAX register
IF ((OPATTR (arg2)) AND 00000100b) or ((OPATTR (arg3)) AND 00000100b)
ECHO ### Function min: No constants allowed as arguments
ELSEIF ((OPATTR (arg1)) AND 00000100b)
; Move constant to EAX if it's not EAX
mov eax, arg1
ELSEIF (SIZE TYPE arg1 NE 4)
ECHO ### Function min: First parameter must be of DWORD type
ELSEIF SIZE TYPE arg2 NE 4
ECHO ### Function min: Second parameter must be of DWORD type
ELSEIF SIZE TYPE arg3 NE 4
ECHO ### Function min: Third parameter must be of DWORD type
ELSEIFDIF <arg1>, <eax>
; Move first value to EAX if it's not EAX
mov eax, arg1
ENDIF
cmp eax, arg2 ; compare arg1 to arg2
cmovg eax, arg2 ; move arg2 to EAX if EAX is greater than arg2
cmp eax, arg3 ; compare arg1 to arg3
cmovg eax, arg3 ; move arg3 to EAX if EAX is greater than arg3
ENDM
在上面的 MACRO 中,OPATTR (arg1)) AND 00000100b
检查 arg1
是否是一个常量值。这很重要,因为 CMOVcc
指令不将常量作为参数。您可以扩展宏以使用条件汇编将常量移动到寄存器或临时变量,但这在上面的代码中没有实现。
SIZE TYPE arg1 NE 4
指令检查参数的大小是否为 4、寄存器或内存 - 防止 MOV
可能出现的错误。您可以扩展它以将 MOVZX
/MOVSX
与进一步的条件装配一起使用。
IFDIF <arg1>, <eax>
检查第一个参数是否等于字符串“EAX”。这样做是为了避免在值已存在的情况下设置 EAX
寄存器。
发生的错误以 ###
开头的控制台回显到控制台,在组装时提供额外信息。
这个 MACRO 远未完成。它只处理一些可能的错误,可以扩展以实现更多的自动化。但恕我直言,它显示了一种值得考虑的方法。
我编写了一个简单的宏,用于查找三个数字中的最小值。在当前状态下,只有当第一个或第三个参数是最小值而不是第二个时,宏才会起作用。我的循环或比较有什么我没有发现的问题吗?或者我应该做些什么不同的事情?任何建议或意见表示赞赏。
findMin MACRO arg1, arg2, arg3
mov eax, arg1
cmp eax, arg2 ; if eax is greater than arg2 swap
jg swap1
cmp eax, arg3 ; if eax is greater than arg3 swap
jg swap2
jmp endMac
swap1: xchg eax, arg2
swap2: xchg eax, arg3
endMac:
ENDM
用于查找 3 个数字的最小值的简化宏(最小值将在 EAX 寄存器中)
findMin MACRO arg1, arg2, arg3
LOCAL L2, L3
mov eax, arg1
cmp eax, arg2
jg l2
cmp eax, arg3
jg l3
jmp endMac
L2: xchg eax, arg2
cmp eax, arg3
jg L3
jmp endMac
L3: xchg eax, arg3
endMac:
ENDM
MASM宏功能非常强大。您可以验证参数的类型,甚至可以进行条件汇编。结合自 Intel P6 系列处理器 以来可用的条件移动 CMOVcc,您可以将程序优化为
min MACRO arg1:REQ, arg2:REQ, arg3:REQ
; Returns result in EAX register
IF ((OPATTR (arg2)) AND 00000100b) or ((OPATTR (arg3)) AND 00000100b)
ECHO ### Function min: No constants allowed as arguments
ELSEIF ((OPATTR (arg1)) AND 00000100b)
; Move constant to EAX if it's not EAX
mov eax, arg1
ELSEIF (SIZE TYPE arg1 NE 4)
ECHO ### Function min: First parameter must be of DWORD type
ELSEIF SIZE TYPE arg2 NE 4
ECHO ### Function min: Second parameter must be of DWORD type
ELSEIF SIZE TYPE arg3 NE 4
ECHO ### Function min: Third parameter must be of DWORD type
ELSEIFDIF <arg1>, <eax>
; Move first value to EAX if it's not EAX
mov eax, arg1
ENDIF
cmp eax, arg2 ; compare arg1 to arg2
cmovg eax, arg2 ; move arg2 to EAX if EAX is greater than arg2
cmp eax, arg3 ; compare arg1 to arg3
cmovg eax, arg3 ; move arg3 to EAX if EAX is greater than arg3
ENDM
在上面的 MACRO 中,OPATTR (arg1)) AND 00000100b
检查 arg1
是否是一个常量值。这很重要,因为 CMOVcc
指令不将常量作为参数。您可以扩展宏以使用条件汇编将常量移动到寄存器或临时变量,但这在上面的代码中没有实现。
SIZE TYPE arg1 NE 4
指令检查参数的大小是否为 4、寄存器或内存 - 防止 MOV
可能出现的错误。您可以扩展它以将 MOVZX
/MOVSX
与进一步的条件装配一起使用。
IFDIF <arg1>, <eax>
检查第一个参数是否等于字符串“EAX”。这样做是为了避免在值已存在的情况下设置 EAX
寄存器。
发生的错误以 ###
开头的控制台回显到控制台,在组装时提供额外信息。
这个 MACRO 远未完成。它只处理一些可能的错误,可以扩展以实现更多的自动化。但恕我直言,它显示了一种值得考虑的方法。