龙芯汇编语言编程(1)

时间:2021-10-07 01:26:00

当前版本: 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接收