您的位置:首页 > 编程语言

龙芯下汇编语言编程(2)

2012-08-08 12:24 148 查看
作者: comcat 发表日期: 2007-03-23 20:11
http://comcat.blog.openrays.org/blog.php?do=showone&tid=314

1. 判断的实现

看这条C语句的汇编实现:

if(i == j)

f = g + h;

else

f = g - h;

------------------------------------------------------------

bne $15, $16, Else # i!=j,则跳转到Else

add $17, $18, $19 # f=g+h

j Exit # 无条件跳转

Else:

sub $17, $18, $19 # f=g-h

Exit:

2. 小于判断的实现

if(i >= j)

f = g + h;

else

f = g - h;

--------------------------------------------------

slt $9, $15, $16 # i<j则$9=1,否则$9=0

bne $9, $0, Else # $9!=0,则跳转到Else

# 上面两条指令实现了“小于则转移”

add $17, $18, $19 # f=g+h

j Exit # 无条件跳转

Else:

sub $17, $18, $19 # f=g-h

Exit:

另一种实现为:

sub $9, $15, $16 # $9=i-j

bltz $9, Else # $9小于0,则跳转到Else

# 上面两条指令实现了“小于则转移”

add $17, $18, $19 # f=g+h

j Exit # 无条件跳转

Else:

sub $17, $18, $19 # f=g-h

Exit:

3. 更多判断的实现

sub t0, s0, s1 # t0 = s0 - s1 -------- [1]

bgez t0, Else # t0大于等于0,则跳转到Else

#上面两条指令实现了大于等于则转移

bgtz t0, Else # t0大于0,则跳转到Else;与[1]联用,实现大于则跳转

blez t0, Else # t0小于等于0,则跳转到Else;与[1]联用,实现小于等于则跳转

bltz t0, Else # t0小于0,则跳转到Else;与[1]联用,实现小于则跳转

Else:

......

加上前面的 bne, beq 相等和不等的跳转指令,可以实现所有的逻辑判断。

4. 循环的实现

while(s==k)

f = g + h;

----------------------------------

loop:

add t1, s3, s3 # t1 = 2*i

add t1, t1, t1 # t1 = 4*i

add t1, t1, s6 # s的地址置于t1

lw t0, 0(t1) # t0 = s

bne t0, s5, Exit # s != k,则停止循环

add s3, s3, s4 # i = i+j

j loop # 跳至loop

Exit:

5. 完整的例子

.text

.globl main

.ent main

main:

.frame $fp, 32, $31 # 帧指针为$fp,帧大小32,返回寄存器$31

.mask 0xc0000000,-4 # $31, $30保存于28($sp),0xc0000000为需保存之寄存器位图

.set noreorder # 关闭汇编器自动填充延迟槽

.cpload $25 # 汇编伪操作,告诉汇编器根据$25寄存器正确设置gp

.set nomacro

addiu $sp, -32 # 栈空间分配32字节

sw $ra, 24($sp) # 保存返回地址

sw $fp, 20($sp) # 保存帧指针

move $fp, $sp # 帧指针就绪

.cprestore 8 # 汇编器伪操作,保存gp于8($fp)

# 预留传参数的栈空间;printf会直接对栈上预留给参数的空间直接操作

# 会覆盖掉8($fp)处的gp,造成调用失败。

addiu $sp, $sp, -20

li $18, 0x3 # 循环次数为3

lui $8, %hi(msg2) # %hi() 求地址的高16位, %lo()求低16位

addiu $17, $8, %lo(msg2) # $17 中为字符串首地址

loop:

move $4, $17 # printf之第一个参数

lw $25, %got(printf)($28) # 获取printf函数地址

jalr $25 # 调用printf

nop

lw $28, 8($fp) # 从栈回复gp,因为进入printf后gp被改写

addiu $18, $18, -1

bne $18, $0, loop # 不等于0,跳转到前面的loop

nop

move $sp, $fp # 栈指针复位

lw $ra, 24($sp) # 返回地址恢复

lw $fp, 20($sp) # 原帧指针恢复

addu $sp, 32 # 回收栈空间

move $2,$0 # 返回值为0

jr $31 # 返回

nop

.end main

.rdata

msg2:

.asciiz "Hello Baby!\n"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: