#assembly #mips #qtspim
#сборка #mips #qtspim
Вопрос:
Этот цикл сканирует строку и для каждого символа, если он равен одной из этих букв, переходит к специальной процедуре:
switch:
add $t1, $zero, $t2
add $t1, $t1, $s2 # $s2 is the address of a string
lb $t0, 0($t1)
blt $t0, 0x41, done
bgt $t0, 0x45, done
beq $t0, 0x41, algoA # These are the jump at the procedure
beq $t0, 0x42, algoB # The parameter in input are setted
beq $t0, 0x43, algoC # Before that SWITCH
beq $t0, 0x44, algoD
beq $t0, 0x45, algoE
endSwitch:
add $t2, $t2, 1
beq $t2, $s1, done
j switch
done:
Для школьного проекта мне нужно, чтобы каждая метка «Algo» должна быть процедурой.
Сначала определяются входные параметры.
Я не знаю, как вернуться с помощью команды jr $ra
из процедуры к этому циклу переключения во время выполнения.
Я думаю, что, возможно, я должен добавить в $ra
регистр endSwitch:
адрес метки.
Я не уверен, что это правильно.
Здесь псевдокод:
while x <= len(string)
switch string[x]
case A: algoA(); x ;
case B: algoB(); x ;
case C: algoC(); x ;
case D: algoD(); x ;
case E: algoE(); x ;
default: x = len(string);
Комментарии:
1.
jr $ra
используется для возврата из чего-то, к чему вы перешли с помощьюjal
, чего вы не делаете.2. Неясно, что вы пытаетесь сделать. Я рекомендую сначала написать предполагаемый алгоритм на языке более высокого уровня.
3. Я изменил вопрос..
Ответ №1:
Это должно сработать.
# void Sw(const char*);
# will call:
# extern void algoA(void), algoB(void),
# algoC(void), algoD(void), algoE(void);
Sw:
.set reorder
addiu $sp, $sp, -32 # reserve 32 bytes on stack:
# 8 unused
# 8 for $s0 and $ra
# 16 reserved for calls to algoX()
# (32 to ensure $sp is properly aligned)
sw $s0, 20($sp) # save $s0 on stack
sw $ra, 16($sp) # save $ra on stack
move $s0, $a0 # algoX() will preserve $sX regs
Sw_loop:
lbu $t0, 0($s0) # read a char
addiu $t0, $t0, -65 # translate 65(A)...69(E) to 0...4
sltiu $t1, $t0, 5 # all others will translate to 5 or more
beqz $t1, Sw_done # done if 5 or more
la $t1, Sw_table # $t1 = address of Sw_table[]
sll $t0, $t0, 2 # multiply 0...4 by 4 to index Sw_table[]
addu $t0, $t0, $t1 # $t0 = address into Sw_table[]
lw $t0, 0($t0) # $t0 = address of algoX()
jalr $t0 # call algoX()
addiu $s0, $s0, 1 # advance the address to the next char
b Sw_loop # repeat
Sw_done:
lw $s0, 20($sp) # restore $s0
lw $ra, 16($sp) # restore $ra
addiu $sp, $sp, 32 # free stack space
jr $ra # return
Sw_table: # table of addresses of algoA()...algoE()
.word algoA
.word algoB
.word algoC
.word algoD
.word algoE
Комментарии:
1. Также есть возможность:
BLTZAL
(переход на значение меньше нуля и ссылка) выполнить условный вызов функции. ( Неполная ссылка на классический набор команд MIPS .) (Но я не вижу, как использовать это илиBGEZAL
для эмуляции условия эквализации / эмуляции «beqal»). Но в этом случае да, индексирование таблицы указателей на функции явно лучше для смежных значений switch / cases операционной системы.2. @PeterCordes В принципе, вы могли бы выполнить серию
addiu -1 bltzal algoA addiu -1 bltzal algoB addiu -1 ...
вместо того, чтобы просматривать таблицу. Однако,bltzal
недоступен на R6 (кроме как в своейnal
форме; R6 предоставляет другую отправку условных ветвей со связыванием). Вышесказанное универсально.