String MIPS:如何获取字符串的第5个字节并用它替换另一个字符串的第4个字节?

String MIPS:如何获取字符串的第5个字节并用它替换另一个字符串的第4个字节?,string,assembly,mips,String,Assembly,Mips,假设我有一根绳子,一根是奶酪,另一根是牛排。我想把第5字节的奶酪放在牛排中的f的位置。我想不出来。以下是我所拥有的: .data string1 = .asciiz "cheese" string2 = .asciiz "beefsteak" .text .globl main main: la $t0, string1 la $t1, string 2 add $t0, $t0, 5 add $t1, $t1, 4 lb $t1, 0($t0) 但这似乎不起作用。我该怎么办呢?除了语法错误

假设我有一根绳子,一根是奶酪,另一根是牛排。我想把第5字节的奶酪放在牛排中的f的位置。我想不出来。以下是我所拥有的:

.data
string1 = .asciiz "cheese"
string2 = .asciiz "beefsteak"

.text
.globl main
main:
la $t0, string1
la $t1, string 2
add $t0, $t0, 5
add $t1, $t1, 4
lb $t1, 0($t0)

但这似乎不起作用。我该怎么办呢?

除了语法错误和忘记存储之外,你的距离很近

使用
string1:.asciiz“cheese”
string1:
是一个与
main:
完全相同的标签,使用相同的语法。只是在另一个区域<代码>名称=.asciiz”“不起作用<代码>=用于定义汇编时间常数,如
string1\u length=。-string1,不用于将数据字节组装到内存中

la$t1,字符串2
在符号名中有一个空格,显然不起作用


lb$t1,0($t0)
销毁
string2
指针。为您的角色临时选择不同的寄存器,例如,
lb$t0,5($t0)
,因为您不再需要该指针

lbu
也可以工作,但您不会读取寄存器的完整字值,因此零扩展和符号扩展之间的选择无关紧要

您需要使用类似于
sb$t0,4($t1)
的东西来存储结果

对于已知的常量偏移量,在运行时执行
addi
是毫无意义的:
lb
sb
也有一个16位立即字段;使用它来简化代码。MIPS只有一种寻址模式:寄存器+imm16。或者,您可以只使用
la
您首先想要的地址,比如
la$t0,string1+5


另外,第5个字节位于
string1+4
。第一个字节是
c
,位于
string1+0
。所以第5个字节是单词的第5个字母,在索引4处。偏移量类似于0索引的C数组。您想要的是
s
中的
cheese
,而不是最后的
e


有趣的事实:您还可以通过寻址一个字符串相对于另一个字符串来在地址生成中保存指令

# assembles (inefficiently) with clang
# untested with MARS or GAS; pretty sure it will work at least with GAS

.data
string1: .asciiz "cheese"
string2: .asciiz "beefsteak"

.text
.globl main
main:
   la   $t0, string1
   lbu  $t1, 4($t0)                   # 5th byte = start+4 of string 1
   sb   $t1, 3+string2-string1($t0)

   jr   $ra   # return
这应该组合成4条机器指令(2条用于
la
,或者如果.data部分是64k对齐的,则可能只有1条。)

在实践中,
clang-target mips
sb
作为伪指令汇编到
lui+addi+sb
,完全没有意义。这些指令上没有重定位,只有小常量,因此更智能的汇编程序不会将
sb
扩展为伪指令

string2-string1
是一个小的编译时常量,因此可以要求汇编程序将其嵌入
lbu
sb
指令的立即数中,再加上一些其他小常量。(如果这两个符号都是在同一节的编译单元中定义的,我们就可以了;如果它们需要由链接器填充,那么减法就有问题了。)

如果我们知道字节在同一个64kiB块中,并且可以让汇编程序只将一个
lui
发送到一个临时,然后将
lbu
sb
发送到符号地址的较低部分,那就更好了。使用气体
%hi(string1)
%low(string1)+string2-string1+3
或其他东西

或者在火星上,如果你要求模拟器将数据段放在一个低地址,你可以使用
lbu$t0,string1($0)
,因为完整地址适合16位立即数

或者使用lbu/sb作为伪指令,让汇编程序发出
lui
+
lbu
,其中lbu immediate提供地址的低位16位,而不是浪费
addiu
ori
在寄存器中生成准确地址,从而在实际加载中浪费立即位

# tested with clang: assembles to lui+lbu,   lui+sb
   lbu $t0, string1+4
   sb  $t0, string2+3
这当然很容易在asm源代码中编写,并且在扩展伪指令后很难真正提高效率,除非您手动利用
string1
string2
位于同一64k对齐区域,并且可以共享
lui