如何确保MIPS从数组输出数字'4'而非ASCII对应的EOT字符
MIPS汇编字符映射输出问题解决
问题概述
我编写了一段MIPS汇编代码,用于读取用户输入并通过键值数组转换为目标字符串,目前遇到两个问题:
- 数组中的映射值是2、3、4这类整数,但MIPS会将其当作ASCII码处理(比如数字4会被识别为EOT控制字符),需要实现输入
$时输出实际数字4的效果。 - 尝试将输出系统调用从4(字符串输出)改为1(整数输出)后,得到了奇怪的数字268501072,无法理解异常原因。
原代码
.data inBuf: .space 80 # input line outBuf: .space 80 # char types for the input line prompt: .asciiz "Enter a new input line. \n" .data tabChar: .word 0x09, 6 # tab .word 0x0a, 6 # LF .word ' ', 6 .word '#', 5 .word '$', 4 .word '(', 4 .word ')', 4 .word '*', 3 .word '+', 3 .word ',', 4 .word '-', 3 .word '.', 4 .word '/', 3 .word '0', 1 .word '1', 1 .word '2', 1 .word '3', 1 .word '4', 1 .word '5', 1 .word '6', 1 .word '7', 1 .word '8', 1 .word '9', 1 .word ':', 4 .word 'A', 2 .word 'B', 2 .word 'C', 2 .word 'D', 2 .word 'E', 2 .word 'F', 2 .word 'G', 2 .word 'H', 2 .word 'I', 2 .word 'J', 2 .word 'K', 2 .word 'L', 2 .word 'M', 2 .word 'N', 2 .word 'O', 2 .word 'P', 2 .word 'Q', 2 .word 'R', 2 .word 'S', 2 .word 'T', 2 .word 'U', 2 .word 'V', 2 .word 'W', 2 .word 'X', 2 .word 'Y', 2 .word 'Z', 2 .word 'a', 2 .word 'b', 2 .word 'c', 2 .word 'd', 2 .word 'e', 2 .word 'f', 2 .word 'g', 2 .word 'h', 2 .word 'i', 2 .word 'j', 2 .word 'k', 2 .word 'l', 2 .word 'm', 2 .word 'n', 2 .word 'o', 2 .word 'p', 2 .word 'q', 2 .word 'r', 2 .word 's', 2 .word 't', 2 .word 'u', 2 .word 'v', 2 .word 'w', 2 .word 'x', 2 .word 'y', 2 .word 'z', 2 .word 0x5c, -1 # if you ‘\’ as the end-of-table symbol .text getline: la $a0, prompt # Prompt to enter a new line li $v0, 4 syscall la $a0, inBuf # read a new line li $a1, 80 li $v0, 8 syscall linearSearch: li $t0, 0 #load 0 into index j linearLoop linearLoop: li $t4, 0 #load 0 into inner index lb $a0, inBuf($t0) #load first byte from input j linearLoopTab linearLoopTab: lb $a1, tabChar($t4) #load first byte from tabchar beq $a1, $a0, found #compares input byte to tab byte, if similar jump to found li $t2, '#' #makes t2 '#' beq $a0, $t2, exit #if current input byte is '#', exit addiu $t4, $t4, 8 #add index j linearLoopTab #loop back found: addi $t4,$t4,4 #selects correct pos for encrypted message lb $a2, tabChar($t4) #load first byte from input subi $t4,$t4,4 #reverting pos sb $a2, outBuf($t0) #store it into outbuff at index pos addi $t0, $t0, 1 #add index j linearLoop exit: la $a0, outBuf li $v0, 4 #prints and leaves syscall la $a0,inBuf jal clear la $a0,outBuf jal clear li $v0, 10 #exit command syscall clear: li $t0, 0
解决方案
1. 输出数字字符而非ASCII控制码
数组中的映射值是整数,要输出对应的数字字符,需要将整数转换为ASCII码。ASCII中数字'0'的编码是48,给每个映射值加上48即可得到对应数字的ASCII码:
- 例如整数4 → 4 + 48 = 52,对应ASCII的
'4'
修改found段代码:
found: addi $t4,$t4,4 # 定位到映射值位置 lb $a2, tabChar($t4) # 读取映射的整数 addi $a2, $a2, 48 # 转换为对应数字的ASCII码 subi $t4,$t4,4 # 恢复索引位置 sb $a2, outBuf($t0) # 存入输出缓冲区 addi $t0, $t0, 1 # 输入缓冲区索引+1 j linearLoop
2. 系统调用1输出奇怪数字的原因
系统调用1(li $v0,1)要求$a0存储整数的值,但你直接将outBuf的内存地址加载到$a0,输出的268501072就是outBuf在内存中的地址值,并非目标整数。
如果要用系统调用1输出单个数字,需要逐个取出outBuf中的整数值存入$a0后调用,不能直接传入缓冲区地址。
3. 补充完整clear函数逻辑
原代码的clear函数未完成清空缓冲区的操作,补充如下:
clear: li $t0, 0 clear_loop: sb $zero, ($a0, $t0) # 将当前位置设为字符串结束符0 addi $t0, $t0, 1 bne $t0, 80, clear_loop # 循环清空80字节 jr $ra # 返回调用处
内容的提问来源于stack exchange,提问作者Luca Azevedo
相关产品推荐
相关产品推荐

