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