[了解了MARS中的.macro
后,我决定做一些修改以使我的源代码更具可读性。这样的宏的一个示例是我的str ing len gth宏:
#Gets the length of a string from an address
#Result is in the second operand
#Doesn't count any null-terminators or newlines at the end of the input
#Call example: strlen MyString,$s0
.macro strlen(%str, %i)
la $t0,%str
__strlen_loop:
lb $t1,0($t0)
#Exit the loop if this byte is null ('\0') or a newline ('\n')
beqz $t1,__strlen_end
beq $t1,'\n',__strlen_end
inc $t0 #Increment-by-one macro
j __strlen_loop
__strlen_end:
la $t1,%str
sub %i,$t0,$t1
.end_macro
此宏有效,但是它依赖于预定义的地址才能起作用(%str
)。为了尝试解决此问题,我为v alue字符串宏创建了以下str ing len gth:
#Gets the string length of a value string (stores the string in .data)
#Call example: strlen_v "Hello World!",$s0
.macro strlen_v(%str,%i)
#Create a label for the string
.data
__strlen_v_label: .asciiz %str
.text
#Get the length
strlen __strlen_v_label,%i
.end_macro
不幸的是,还有另一个问题。第二个宏将值字符串存储在.data
中,该字符串仅具有0x30000
个字的空间(地址0x10010000
至地址0x10040000
)。最好将值字符串存储在heap上,因为它具有更多的空间and我将能够更有效地管理内存。
是否可以使用.data
将编译时值字符串存储在堆上[[without”?我发现的唯一示例是用户输入的字符串和已经存储在.data
中的字符串,但这两个都不适用于此问题。
是否可以在不使用.data的情况下在堆上存储编译时值字符串?
不是。根据定义,堆在概念上在程序启动时为空。而且,根据定义,字符串文字是在数据部分中初始化的常量。您只能在运行时分配堆空间,而不能在编译时分配堆空间。因此,在运行时,您可以分配堆空间并将字符串从文字数据移动到堆...
但是,请注意,MARS和QtSPIM允许为.data
提供参数,这是放置后续内容的位置。例如,我们可以执行.data 0x10040000
,这将导致随后的字符串文字放置在该位置。但是,这将干扰正常的堆操作,因为您的第一个sbrk syscall仍将返回0x10040000
,这是使用.data 0x10040000
放置在其中的字符串文字所占用的内存,因为sbrk syscall并不知道该指令。
从长远来看,将字符串长度定义为函数而不是宏可能会更符合您的期望: