Assembly 装配编码标准/最佳实践

Assembly 装配编码标准/最佳实践,assembly,coding-style,mips,Assembly,Coding Style,Mips,我知道8086汇编,现在我正在通过阅读书籍和学习MIPS汇编,但我从未停止思考汇编的编码标准/最佳实践。我每天都想让自己成为一名更好的开发人员,然后想知道这一点来提高自己。如何了解更多有关汇编编码标准和最佳实践的信息?最佳实践是一种社会现象,取决于您所处的社会,因此您最好的答案是从您希望与之交互的任何环境中读取现有MIPS asm代码 在我自己的世界里,我想到的例子有Linux内核的汇编程序部分、GCC的MIPS启动代码或glibc的MIPS端口的汇编程序片段 如果您主要与其他项目进行交互,最好

我知道8086汇编,现在我正在通过阅读书籍和学习MIPS汇编,但我从未停止思考汇编的编码标准/最佳实践。我每天都想让自己成为一名更好的开发人员,然后想知道这一点来提高自己。如何了解更多有关汇编编码标准和最佳实践的信息?

最佳实践是一种社会现象,取决于您所处的社会,因此您最好的答案是从您希望与之交互的任何环境中读取现有MIPS asm代码

在我自己的世界里,我想到的例子有Linux内核的汇编程序部分、GCC的MIPS启动代码或glibc的MIPS端口的汇编程序片段


如果您主要与其他项目进行交互,最好吸收和模仿该社区的编码实践。

良好的asm风格在ISA中非常普遍(对于同一CPU,asm的不同方言)。编译器输出(如gcc/clang)通常完成我在下面提到的所有工作,这是一个很好的指导原则。(C编译器输出通常是优化小函数的良好起点。)

通常,指令缩进比标签和汇编指令更深一层

将操作数缩进一个一致的列(这样,不同长度的助记符不会使代码变得参差不齐,并且很容易向下扫描一个块,并将每条指令的目标寄存器视为第一个操作数)1

将指令行上的注释缩进右侧的一致列,远远超过操作数,以避免视觉干扰

将相关指令块分组在一起,并用一个空行将它们分隔开。(或者,如果您正在通过调度指令来优化顺序CPU,则实际上无法做到这一点,需要使用注释来跟踪每条指令处理的问题的哪一部分。使用不同级别的注释缩进可能会有所帮助)


脚注1:
除了MIPS存储指令,如
sw$t0、1234($t1)
其中第一个操作数实际上是源;他们选择让asm源对加载和存储使用相同的操作数顺序,可能是因为它们在机器代码中都是I型指令。这是RISC加载/存储体系结构中典型的asm,因此需要习惯来自CISC,其中
mov-eax,
是一个加载,
mov[rdi],eax
是一个存储。和
add[rdi],eax
两者都是


示例:用于无符号整数的
atoi
函数,用于带有分支延迟槽的实MIPS。但不是MIPS I,没有加载延迟插槽。尽管我试图避免加载使用暂停。()

#无符号十进制ASCII字符串到整数
#输入:以非数字字符结尾的$a0-ASCII字符串中的字符*
#输出:整数,单位为$v0
#打击者:$t0,$t1
原子能机构:
#剥离第一次迭代以避免0*10的乘法
lbu$v0,0($a0)
加上$v0,$v0,-'0'#位=*p-'0'
sltu$t0、$v0、10

bnez$t0,.Lloop#输入项#如果未签名(!digitGood goals…)您能说明您想要回答的问题吗?
# unsigned decimal ASCII string to integer
# inputs: char* in $a0 - ASCII string that ends with a non-digit character
# outputs: integer in $v0
# clobbers: $t0, $t1
atoi:
    # peel the first iteration to avoid a 0 * 10 multiply
    lbu    $v0,  0($a0)
    addiu  $v0, $v0,  -'0'          # digit = *p - '0'
    sltu   $t0, $v0,  10
    bnez   $t0, .Lloop_entry        # if unsigned (! digit<10) 
    nop                              # doing work for the next iteration here hurts ILP for in-order CPUs
    #addu   $t2, $v0, $v0            # total * 2  (branch delay slot)

    # invalid non-digit input
    jr     $ra                      # return 0
    move   $v0, $zero


.Lloop:                           # do {
    addu   $v0, $v0, $v0            # total *= 2
    addu   $t0, $t0, $t1            # total*8 + digit

    addu   $v0, $v0, $t0            # total*10 + digit = total*2 + (total*8 + digit)

.Lloop_entry:
    lbu    $t0, 1($a0)
    addui  $a0, $a0, 1              # t0 = *(p++ + 1)

    addiu  $t0, $t0,  -'0'          # t0 = digit
    sltu   $t1, $t0,  10
    bnez   $t1, .Lloop           # while(digit<10);
    sll    $t1, $v0, 3

    jr     $ra
    nop