将flags寄存器用作布尔返回值被认为是不好的做法吗?

时间:2018-01-22 12:05:53

标签: assembly x86 coding-style

我正在x86汇编程序中编写一些程序来修改ZF作为返回布尔值的方法,所以我可以这样做:

call is_value_correct
jz not_correct

我想知道这是否被认为是不好的做法,因为一些编码标准说应该在AX寄存器中返回简单的值。

1 个答案:

答案 0 :(得分:8)

是的,如果它使您的代码运行得更快和/或整体更小,请执行此操作。

手动编写asm的一个优点是能够使用自定义调用约定函数,即使它们不是私有帮助函数或宏。这包括能够"返回"不同寄存器中的多个值,基本上可以随心所欲。

与任何自定义调用约定一样,您需要做的就是用注释记录它。以下是您可以使用特定且有意的非标准事物撰写此类评论的示例。

# inputs:   foo in EAX (zero-extended into RAX), bar in EDI
# pre-requisites: DF=0
# clobbers: RCX, RDX, AL (but not the rest of EAX)
# returns:  AL = something,  ZF = something else
my_func:
   ...
   setc al
   ...
   something that sets ZF
   ret

如果你愿意为了风格或可读性而牺牲效率,你可能不应该在2018年首次写asm,因为编译器能够在大多数时间内产生好的asm,而你很少需要编写自己的引导扇区或其他任何东西。 (即表演是手写asm的主要用例,只有当你全力以赴表现时才能表现出来。)

是的,手写的asm可能成为一个难以理解/无法维护的混乱,但如果它具有合理的语义含义,那么这个优化不会成功你的代码一团糟。

这样做甚至有先例:x86-64 OS X system calls use CF as the error/no-error status,与rax返回值分开。与Linux不同,RAX指示错误从-4095到-1返回值,尽管它们使用相同的x86-64 System V ABI /调用约定。

某些DOS int 0x21系统调用和PC BIOS int 0x10函数具有类似的标志返回系统。它允许调用程序分支出错,因此它可以节省代码大小(测试或cmp)并避免需要带内错误信号。