为nasm指令和宏缩进

3

通常使用nasm语法时,指令相对于标签进行缩进,如下所示:

.top:
    dec eax
    jnz .top

汇编指令和宏,例如%rep,应该如何处理?是否像这样:
.top:
    %rep 10
    dec eax
    %endrep
    jnz .top

或者

.top:
%rep 10
    dec eax
%endrep
    jnz .top

或者甚至可能是其他一些指令,其中指令本身暗示了额外的缩进级别 - 但这仅适用于具有开放和关闭部分的“作用域”指令,例如%rep%endrep,而不适用于独立或非嵌套的指令。

.top:
    %rep 10
        dec eax
    %endrep
    jnz .top

还是其他什么?


投票关闭此问题的人请注意:它并没有要求提供外部参考。适当的关闭理由应该是“主观性强”,正如 [tag:coding-style] 标签的使用指南中所述。我还是选择回答了这个问题,因为 NASM 没有太多已经确立的风格指南会产生冲突。 - Peter Cordes
@PeterCordes - 存在代码格式化标签似乎表明至少一些代码格式化问题是相关主题。我想有问题的那些,会被认为是“不具建设性”的,例如基于个人观点的问题,比如“在C语言中使用什么大括号风格”或者命名约定,因为有很多选项。我希望在nasm的情况下,至少在指令方面有一个普遍接受或历史上使用的风格,因此它是具有建设性的。 - BeeOnRope
我认为[tag:code-formatting]应该是关于编写或使用格式化代码的工具。 这个标签最近的大部分问题都是关于这方面的。 - Peter Cordes
@PeterCordes - 很好的观点,尽管这可能只是因为这是今天与代码格式相关的大部分问题:人们在格式化他们想要的代码方面遇到麻烦,而不是关于格式约定的基本问题。 - BeeOnRope
@MichaelPetch:我喜欢你的建议,已经更新了我的答案,并解释了为什么这是个好主意。 - Peter Cordes
2个回答

3

传统上,汇编代码以四栏式布局书写。这四栏分别是:

  1. 标签
  2. 助记符
  3. 操作数
  4. 注释

返工卡片起步的传统汇编程序通过每个单词所在的列来识别其含义。现代汇编器使用更复杂的解析器,允许汇编程序具有自由格式的布局。然而,为了易读性,最好遵循传统的布局。

正如您所看到的,第二列中写有“助记符”。这指示汇编指令和指令集。因此,回答你的问题,这个指示将放在其他指令所在的同一列中。我建议像你的 %rep ... %endrep 示例一样,通过空行突出大括号:

.top:   %rep 10
        dec eax
        %endrep

        jnz .top

1
%rep这样的指令是一种“元”事物,对其他行(在rependrep之间)产生影响,因此它们非常不像指令或扩展为多个助记符的宏。 - Peter Cordes
@rcgldr 不是真的。在BSD和汇编程序中,C代码始终使用制表符进行缩进(每个制表符停止8个空格),在连续行中使用4个空格。历史上设置了特殊的制表位。UNIX仍然有tabs(1)实用程序来为各种大型机汇编器设置制表位。 - fuz
@rcgldr 书籍中的间距并不代表实际使用的间距,主要是出于布局考虑。如果您查看当时的C代码,几乎全部都是用制表符缩进的,制表位仍然设置为每8个位置一个制表位。 - fuz
@rcgldr 对于汇编语言编程,制表位的间距是不同的。请参考tabs(1)手册,了解不同(大型机)汇编器常用的制表位间距。GNU man页面没有列出确切的制表位间距,但POSIX和BSD有。 - fuz
@fuz - 对于Microsoft Masm(X86),将第1列称为1,然后是1、9、17列,在某些“制表符”边界处带有注释,可以选择使用制表符== 8个空格。对于IBM 360系列汇编程序,然后是列1、10、16、36或40,通常不使用制表符,因为此标准基于打孔卡片,即使存储在磁盘或磁带上也是如此。 - rcgldr

2
我喜欢从C预处理器样式中借鉴,将NASM预处理器指令全部缩进到最左边。(或者在嵌套的%if和其他块影响指令的情况下,使用2个空格进行缩进,因此即使是嵌套的%if,它通常也会从指令助记符开始的列的左侧开始)。
%rep / %endrep预处理器指令会影响它们之间的指令助记符,因此您肯定希望它们突出,而不是在周围的指令中丢失。当您看到一个时,您希望能够立即在视觉上发现另一个,而不是在助记符列中向上或向下扫描第一个匹配项。特别是如果有任何嵌套或其他预处理器技巧。
通常,您只会在多个指令或数据块上使用%rep;否则,您将使用time 10 dec eax。(或者您在%rep内部使用%assign创建像dec r10d / dec r11d / dec r12d / ...这样的块) 因此,实际用例不会像这个示例那么简单,并且匹配的%endrep / %rep将远离2行。
当您混合使用标签和%if / %rep指令时,可能更难看到标签。您不希望%rep也在最左边的列上杂乱无章。
Michael Petch的建议进一步缩进要重复的指令是一个很好的建议。它们本来就很特殊,读者注意到这一点很重要。但是,它们像指令一样扩展到一块指令,因此在指令列中启动%rep非常有意义,并且缩进所包含的块使其易于找到该块的开始/结束。
%if USE_SIMPLE_LOOP
.top:
    %rep 10
        imul     ecx, edx
        dec      edx
    %endrep
    sub      eax, 10
    jg      .top

请注意,我将我的操作数缩进得更远,为助记符留出空间,使操作数列不会变得凌乱。
我故意将分支目标缩进了1列,这使它稍微突出而不显得丑陋。特别是当目标是以 . 开头的本地标签时。
但是,根据%rep的用例,将指令保留在正常列中并在标签和指令之间使用一列可能会看起来更好。
%if  USE_SIMPLE_LOOP
.top:                               ; could indent the label by a column or two inside %if
  %rep 10                           ;  unroll 
    imul     ecx, edx
  %endrep
    sub      eax, 10
    jg      .top
%endif


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接