有关电话和电话号码
· 阅读需 24 分钟
工作原因经常需要处理手机号,一般都是用一些开源库来解析。最近看了一下开源库的实现,发现对电话号码的定义还挺复杂的。所以结合之前了解到的一些 PSTN 的知识对电话和电话号码相关的内容进行了整理。
工作原因经常需要处理手机号,一般都是用一些开源库来解析。最近看了一下开源库的实现,发现对电话号码的定义还挺复杂的。所以结合之前了解到的一些 PSTN 的知识对电话和电话号码相关的内容进行了整理。
在上篇文章说到了学习Plan 9基础可以为我们揭开底层的一些细节,从而通过实践去探究原理。接下来就以Plan 9为基础,从不同角度去探索Golang语言吧。
如果你还没有阅读Plan 9相关的知识,推荐阅读Plan9 & Go Assembler
环境说明:Mac m1 (ARM架构)、Golang v1.23.2
这里简单回顾几个比较重要的知识点吧
Plan 9汇编伪寄存器
Plan 9源操作数与目标操作数方向,源操作数在前,目的操作数在后
movl $0x2, %eax
将立即数0x2移动到eax寄存器在函数调用的时候,会经常看到这样一段的函数序言,主要的作用就是保存「调用者的」BP
pushq %rbp
movq %rsp, %rbp
subq %16, %rsp
大致步骤如下
此时函数只包含返回地址(即调用函数的下一条指令的地址)
pushq %rbp
将调用者的栈帧指针(%rbp
)压入栈
保存上一个栈帧的基地址,用于函数返回时恢复调用者的栈帧
moveq %rsp, %rbp
将当前栈指针%rsp的值赋给%rbp, 建立当前函数的栈帧基地址 标记当前函数的栈帧起点
subq $16, %rsp
将栈指针%rsp向下移动16字节,为局部变量分配空间 完成局部变量栈空间的分配
下面就来编写代码,验证一下吧
go tool compile -S -N -l add_func.go
// base/prologue/add_func.go
package main
func add(a, b int) int {
return a + b
}
func main() {
_ = add(1, 2)
}
MOVD.W R30, -32(RSP)
保存调用者的链接寄存器(R30)到栈中。MOVD R29, -8(RSP)
保存当前帧指针(R29)到栈中。SUB $8, RSP, R29
更新栈帧指针R29。0x0000 00000 TEXT main.add(SB), NOSPLIT|LEAF|ABIInternal, $32-16
0x0000 00000 MOVD.W R30, -32(RSP)
0x0004 00004 MOVD R29, -8(RSP)
0x0008 00008 SUB $8, RSP, R29