【问题标题】:C to MIPS assembly confusionC 到 MIPS 汇编混淆
【发布时间】:2016-07-20 04:08:30
【问题描述】:

我是汇编编码的新手,我遇到了一个问题,将以下 C 代码传输到 MIPS 汇编。

b[8] = b[i-j] + x ;

变量 i,j,x 在寄存器 7,4 和 15 中,数组 b 的基地址是十进制的 2,870,220。

我想出了以下解决方案

 lui $2, 0x002B
 ori $2, $2, 0xCBCC
 sub $3, $7, $4
 add $3, $2, $3
 lw $12, 0($3)
 addu $12, $12, $15
 sw $12, 32($2) 

但是当我检查答案时,又多了一行

sll $3, $3, 2 

在减法指令之后。

有人能解释一下为什么我们需要将寄存器 $3 的内容乘以 4 吗?

【问题讨论】:

  • 数组是字(32 位)大小而不是字节大小?
  • 问题没有指定任何关于数组的内容。
  • 它可能是字大小的。实际上我忘记了 mips 的语法,lw 是加载词是吗? 32位的东西?什么是加载字节?磅?如果 lw 是 32 位负载,那么您需要将偏移量与一个字对齐,因此乘以 4 以获得地址的偏移量而不是索引

标签: assembly mips mips32


【解决方案1】:

我会举例说明。

假设我们将这 5 个字节存储在内存位置 0x00000000 到 0x00000004 中(例如,我忽略了内存映射):

| 0x27 | 0x82 | 0x97 | 0x42 | 0x11 |

在内存地址 0x00000000 加载一个字时,它会为您提供 32 位字 0x27829742,因为它连接了基地址的下 4 个字节。

但是,在内存地址 0x00000001 处,您会得到 0x82974211。


我认为这种误解来自于 operator[] 是如何在数组中实现的,所以我将尝试对此进行扩展。考虑以下 C 代码:

int arr[3] = { 1, 3, 5 };
printf("%d\n", arr[2]); // print third element

访问arr[2]时,必须考虑到数组元素的size。假设 int 标准是 32bit(4byte),编译时会得到如下代码:

int arr[3] = { 1, 3, 5 };
printf("%d\n", *(arr + (2 * sizeof(int)))); // print third element

在这种情况下,它将数组的基指针偏移一个整数的字节数乘以正在访问的索引,然后得到指定的元素。

总结:

内存块以 8 位字节对齐,而不是 32 位字。

【讨论】:

  • 说明最后一点的更好方法:内存地址指的是字节,而不是整个 32 位字。所以两个相邻的单词在地址上相差 4。另外,我知道你想用 C 的“它如何编译”版本说什么,但是你显示的代码仍然是有效的 C,它可以将索引缩放两次!也许说从((char*)arr) + 2 * sizeof(int)加载一个4字节的字。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-18
  • 2017-03-15
  • 1970-01-01
  • 2014-08-16
  • 2012-01-20
相关资源
最近更新 更多