2番目の編集:
さて、これはあなたの例のチェックコードに対して正しく機能するようになりましたが、隠れたバグや間違いがないことを保証することはできません. 16 文字のフィスカル コードを指定すると、制御コードが正しいか正しくないかが出力されます。
奇妙な位置に非常に多くのパターンを見つけることができず、複雑にするために何もしたくなかったため、非常に反復的です. かなりシンプルにして、徹底的にコメントしました。
ご質問やご意見がございましたら、お気軽にお問い合わせください。
# Italian Fiscal Code Calculation in MIPS
.data
ArraySpace: .space 18
lookupTableOdd: .ascii "10579"
msgOk: .asciiz "\nCorrect control code!"
msgFail: .asciiz "\nIncorrect control code!"
.text
main:
li $v0, 8 # read string to store into ArraySpace
la $a0, ArraySpace # load address of fiscal value attempt
li $a1, 18 # length 16 + '\n'
syscall # tell system to read string
addi $t2, $a1, -2 # length of string
li $t3, 0 # i = 0 (our string iterator)
jal loop # actually loop through input string
li $t9, 26 # load 26 for divison
div $t5, $t9 # divide total in $t5 by 26
mflo $t4 # move result into $t4
jal controlCode # calculate control code
move $t5, $t4 # move our calculated check code to $t5
jal checkCode # check control code
li $v0, 10 # exit code
syscall # terminate nicely
checkCode:
addi $t2, $t2, -1 # backup to last index in string
lbu $t4, ArraySpace($t2) # load the control code of the input string (last index)
blt $t4, 65, endLoop # should not get something below 65
bgt $t4, 122, endLoop # not valid character above 122
addi $t4, $t4, -65 # get alphabet value 0-25
bge $t4, 32, case_convert_ch # if a-z we have to sub 32
beq $t5, $t4, checkOk # checkcode is equal to calculated code
j checkFail # else fail
checkFail:
li $v0, 4 # print fail
la $a0, msgFail # load failed code message
syscall # print it
j endLoop
case_convert_ch:
addi $t4, $t4, -32 # make lowercase 'A'-'a'=-32
beq $t4, $t5, checkOk # if equal print ok
j checkFail # else fail
controlCode:
bgt $t4, 4, checkDigit # >4 is two digit value
lbu $t4, lookupTableOdd($t4) # fetch corresponding value
addi $t4, $t4, -48 # get digit value
j endLoop
checkDigit: # this is for 5 to 9 in odd positions
sub $t4, $t4, 5 # value - 5
mul $t9, $t4, 2 # multiply this by 2
li $t4, 13 # the base is 13
add $t4, $t4, $t9 # 13 + factor of 2
j endLoop
case_convert_cc:
addi $t4, $t4, -32 # uppercase: 'A'-'a'=-32
bgt $t4, 4, oddDigit # >4 is two digit value
lbu $t4, lookupTableOdd($t4) # fetch corresponding value
addi $t4, $t4, -48 # get digit value
j endLoop
checkOk:
li $v0, 4 # print string
la $a0, msgOk # load ok message
syscall # print it
j endLoop
loop:
bge $t3, $t2, endLoop # if greater than length of string end
andi $t8, $t3, 1 # logical AND result into $t2 (even = 0, odd = 1)
beq $t8, $zero, evenLoop # on even positions goto evenLoop
j oddLoop # on odd positions goto oddLoop
evenLoop:
lbu $t4, ArraySpace($t3) # load the i index of the input string
blt $t4, 48, endLoop # should not get something below 48
bgt $t4, 57, evenCharLoop # not a digit
addi $t4, $t4, -48 # get digit value
j continueLoop
oddLoop:
lbu $t4, ArraySpace($t3) # load the i index of the input string
blt $t4, 48, endLoop # should not get something below 48
bgt $t4, 57, oddCharLoop # not a digit
addi $t4, $t4, -48 # get digit value
bgt $t4, 4, oddDigit # >4 is two digit value
lbu $t0, lookupTableOdd($t4) # fetch corresponding value
addi $t4, $t0, -48 # get digit value
j continueLoop
oddDigit: # this is for 5 to 9 in odd positions
sub $t4, $t4, 5 # value - 5
mul $t9, $t4, 2 # multiply this by 2
li $t4, 13 # the base is 13
add $t4, $t4, $t9 # 13 + factor of 2
j continueLoop
evenCharLoop:
blt $t4, 65, endLoop # should not get something below 65
bgt $t4, 122, endLoop # not valid char
addi $t4, $t4, -65 # get alphabet value
bge $t4, 32, case_convert_even # if a-z we have to sub 32
add $t5, $t5, $t4 # add the alpha value A-Z to our sum
add $t3, $t3, 1 # i++
j loop
oddCharLoop:
blt $t4, 65, endLoop # should not get something below 65
bgt $t4, 122, endLoop # not valid char
addi $t4, $t4, -65 # get alphabet value
bge $t4, 32, case_convert_odd # if a-z we have to sub 32
j oddProcess
## this should probably be done better but I did not find many patterns ##
oddDigitCheck:
ble $t4, 9, oddDigit # F>=x<=J is two digit value of factor 2
sub $t4, $t4, 10 # >=K
blt $t4, 2, KL # 0-K 1-L
blt $t4, 4, MN # 2-M 3-N
beq $t4, 4, O # 4-O
blt $t4, 7, PQ # 5-P 6-Q
beq $t4, 7, R # 7-R
blt $t4, 11, STU # 8-S 9-T 10-U
beq $t4, 11, V # 11-V
beq $t4, 12, W # 12-W
blt $t4, 16, XYZ # 13-X 14-Y 15-Z
oddProcess:
bgt $t4, 4, oddDigitCheck # >E could be two digit value
lbu $t0, lookupTableOdd($t4) # fetch corresponding value (A-E)
addi $t0, $t0, -48 # get digit value
add $t5, $t5, $t0 # add the digit to our sum
add $t3, $t3, 1 # i++
j loop
case_convert_even:
addi $t4, $t4, -32 # to uppercase: 'A'-'a'=-32
j continueLoop
case_convert_odd:
addi $t4, $t4, -32 # to uppercase: 'A'-'a'=-32
j oddProcess
endLoop:
jr $ra # jump and return
XYZ:
sub $t4, $t4, 13 # X or Y or Z
li $t9, 25 # base is 25
sub $t4, $t9, $t4 # 25 - (0,1,2)
j continueLoop
W:
li $t4, 22 # W = 22
j continueLoop
V:
li $t4, 10 # V = 10
j continueLoop
STU:
sub $t4, $t4, 8 # S or T or U
mul $t9, $t4, 2 # mult by 2
li $t4, 12 # base of 12
add $t4, $t4, $t9 # add factor
j continueLoop
R:
li $t4, 8 # R = 8
j continueLoop
PQ:
sub $t4, $t4, 5 # P or Q
mul $t9, $t4, 3 # mult by 3
li $t4, 3 # base of 3
add $t4, $t4, $t9 # add factor
j continueLoop
O:
li $t4, 11 # O = 11
j continueLoop
MN:
sub $t4, $t4, 2 # M or N
mul $t9, $t4, 2 # mult by 2
li $t4, 18 # base of 18
add $t4, $t4, $t9 # add factor
j continueLoop
KL:
mul $t9, $t4, 2 # mult by 2
li $t4, 2 # base of 2
add $t4, $t4, $t9 # add factor
j continueLoop
continueLoop:
add $t5, $t5, $t4 # add the digit to our sum
add $t3, $t3, 1 # i++
j loop