当前版本: 0.1
完成日期: 2007-3-22
作者: Dajie Tan <jiankemeng@gmail.com>
1. Hello World
从经典的Hello World开始:
.text #表示将后面的代码编译后置于目标文件的.text段
.globl main #声明main为全局变量。该变量名会置于符号表中
.ent main #告诉汇编器main函数在此开始,调试用
main: #标号,表示main函数的始地址,有实际意义
lui $4, %hi(cmd) #Load Upper Immediate
addiu $4, $4, %lo(cmd) #execve的第一个参数置于a0, 为字符串/bin/echo的首地址
lui $5, %hi(argv) #%hi, %lo为汇编器定义的宏,分别求地址的高16和低16位
addiu $5, $5, %lo(argv) #execve的第二个参数置于a1, 为字符指针数组的首地址
move $6, $0 #第三个参数a2为0 (NULL)
li $2, 4011 #将execve系统调用号置入v0寄存器
syscall #系统调用
move $2, $0 #main的返回值0, 置于v0
jr $31 #main返回
.end main #告诉汇编器main在此结束,调试用
.data #以下内容位于目标文件的数据段
cmd:
.asciiz "/bin/echo"
msg:
.asciiz "Hello world!"
argv:
.word cmd # /bin/echo的首地址
.word msg # Hello world!的首地址
.word 0x0 # NULL
存为helloworld.s,gcc helloworld.s -o hw 编译之,
执行结果:
Hello world!
2. 带立即数的指令
汇编或机器语言中,称指令中的常数为立即数(Immediate)
上面的例子我们看到这些指令:lui, li, addiu
lui: Load Upper Immediate, 加载立即数到寄存器的高16位
lui t0, 0xaa55 # t0 = 0xaa55 0000
addiu t0, t1, 64 # t0 = t1 + 64,为无符号相加
带立即数的指令,指令编码格式属于I-型,回忆下其格式: 6, 5, 5, 16 预留给立即数的空间是16位,因此指令中的立即数范围,无符号为0~2^16-1, 有符号为-2^15~2^15-1
如果超过范围,可以先用 li 将立即数置入寄存器,然后使用add运算
3. li (Load Immediate)
li (Load Immediate) 没有16位的限制,因为它不是单一的一条指令,而是由汇编器定义的一个“复合”指令,一般称其为宏指令。
常见情况下,li的展开:
li t0, -5 -----> addiu t0, zero, -5
li t0, 0x8000 -----> ori t0, t0, 0x8000
li t0, 0x12345 -----> lui t0, 0x1
ori t0, t0, 0x2345
4. 龙芯下,系统调用的约定
v0: 用于置系统调用号
a0~a3: 置前四个参数,后面的参数用栈传
syscall 系统调用触发指令
返回值依旧使用v0接收