如何使用mips汇编中的地址设置按钮和LED?

问题描述 投票:0回答:1

系统有 4 个按钮,分别命名为 A 到 D。按钮的内存映射到地址 0xffffe440。按钮的状态在位索引 7 到 4 处给出,其中按钮 A 在索引 7 处给出,按钮 D 在索引 4 处给出。位值 1 表示该按钮当前被按下。该系统有8个LED灯,内存映射在地址0x17880010。 LED 灯位于位索引 12 至 5。

做什么:

创建一个永远循环的程序。在循环中,读取按钮A和D的状态,如果按下A,则打开LED灯以显示十进制值13的二进制表示。如果松开 A,则应继续显示值 13,直到按下按钮 D。如果按下 D,所有 LED 灯都会关闭。如果再次按下按钮 A,则应再次显示值 13,依此类推。如果同时按下 A 和 D,则 LED 应关闭。当程序启动时,如果没有按下任何按钮,所有 LED 灯都应该关闭。请注意,部分正确的解决方案可以获得积分。

写入内存映射 I/O 端口时,无需考虑端口的其他一些未使用位是否发生更改。

我尝试过的:

这是我尝试过的,答案中的解决方案非常短,但我的解决方案很长,可能不漂亮,但对我来说看起来是正确的,我想听听你们的想法。 (我不想重写它的原因是因为我想知道这是否正确,我正在做旧考试)

funct : 
      lui $t0, 0xffff
      ori $t0, $t0, 0xe440
      lui $t1, 0x1788
      ori $t1, $t1, 0x0010
loop : 
     lw   $t2, 0($t0)
     andi $t3, $t2, 0x90
     addi $t4, $0, 0x90
     bne  $t3, $t4, check_A
     andi $t9, $t9, 0x0
     sw   $t9, 0($t1)
     j    loop

check_A : 
     andi $t3, $t2, 0x80
     addi $t4, $0, 0x80
     bne  $t3, $t4, check_D
     andi $t9, $t9, 0x1a0
     sw   $t9, 0($t1)
     j    loop
check_D:
     addi $t4, $0, 0x10
     andi $t4, $0, 0x10
     bne  $s3, $t4, exit
     andi $t9, $t9, 0x0
     sw   $t9, 0 ($t1)
     j    loop
exit:
     j    loop
 
assembly embedded mips hardware low-level
1个回答
0
投票

有一行代码并不符合您的想法:

andi $t9, $t9, 0x1a0

这看起来是错误的,因为它(a)依赖于

$t9
的原始值,并且(b)用常量掩盖它,几乎没有任何效果。
$t9
的传入值很可能是 0,因此在这条指令之后仍然是 0。

可能你想要:

addi $t9, $0, 0x1a0

虽然我不得不承认我不明白这个恒定值从何而来。我本来想把 13 放在那里(或十六进制,0xD)。


以下:

check_D:
     addi $t4, $0, 0x10
     andi $t4, $0, 0x10

也肯定没有做你想做的事。即将

$t4
设置为 0x10,然后用 0x10 进行掩码,从而使
$t4
保留为 0x10。需要修复寄存器用法,使其更像
Check_A
部分。


为了缩短程序,让我们观察一下

lw
允许使用 16 位有符号立即数。因此,您可以在没有基址寄存器的情况下访问 0xffffe440,如下所示:

lw $t2, 0xe440($0)   # Note using $0/$zero as base register

这将访问位置 0xffffe440,并且无需将

$t0
设置为按钮的基址寄存器,因此节省了 2 条指令 (lui/ori)。

接下来,内存位置0x17880010确实需要基址寄存器,但仅限于0x1788部分,因为0x0010部分可以放入

sw
指令的偏移量中,因此节省了1条指令(ori)。

$0 寄存器始终保存 0,所以:

 andi $t9, $t9, 0x0
 sw   $t9, 0($t1)

更简单的做法如下:

 sw   $0, 0($t1)

(顺便说一句,

andi
是一种不寻常但还可以的清除$t9的方法,大多数人会使用
addi $t9, $0, 0
add $t9, $0, $0

标记为

exit
的分支应该直接分支到
loop
,从而允许消除该标签和另一条指令 (
j
)。

您还可以通过将常量 0x90 等放入其自己的专用寄存器中来动态缩短循环,而不是在循环内重新加载这些常量。这不会降低静态指令计数,但有助于动态指令计数。

© www.soinside.com 2019 - 2024. All rights reserved.