我会尽量简短。我的程序遇到了无限循环问题,甚至在尝试使用调试器后,我也遇到了无限循环问题。
我要制作的程序是我老师的一项作业,目的是对使用.word的IP地址表进行排序。我完成了大约95%的程序,最后一个问题是当我键入193.0.0.0时,遇到了这个无限循环,该循环的结构与其他两个相同,没有问题。在此程序中,要使C类域IP地址与IP地址的前3个数字匹配,需要与用户输入匹配,否则,请继续表的其余部分。 发生的特定问题是,当它找到第一个数字的匹配项并继续尝试与第二个数字匹配,然后再与第三个数字匹配。如果第二个数字或第三个数字不匹配,它会跳回到循环中,但随后会被困在那里,这本不应该发生。至少,根据我的判断,应该不会。
匹配效果很好,如果不匹配,则有问题,但是我不确定为什么希望新的眼睛能够帮助我解决问题。 另外,对代码中的任何草率和冗长的代码表示抱歉,这很简单。感谢您的帮助。
.data
MESSAGE1: .asciiz "Enter an IP address\n"
MESSAGE2: .asciiz "First: "
MESSAGE3: .asciiz "Second: "
MESSAGE4: .asciiz "Third: "
MESSAGE5: .asciiz "Fourth: "
MESSAGE6: .asciiz "The IP address you entered: "
MESSAGE7: .asciiz "."
MESSAGE8: .asciiz "\nClass A address\n"
MESSAGE9: .asciiz "\nClass B address\n"
MESSAGE10: .asciiz "\nClass C address\n"
MESSAGE11: .asciiz "\nClass D address\n"
MESSAGE12: .asciiz "\nInvalid domain class\n"
MESSAGE13: .asciiz "\nProgram successfully completed . . .\n"
MESSAGE14: .asciiz "\n"
MESSAGE15: .asciiz "Matching domain found at line: "
MESSAGE16: .asciiz "Matching domain was NOT found . . . \n"
ERROROVER: .asciiz "The entered number is larger than 255.\n"
ERRORUNDER: .asciiz "The entered number is smaller than 0.\n"
IP_ROUTING_TABLE_SIZE:
.word 10
IP_ROUTING_TABLE:
# line #, x.x.x.x -------------------------------------
.word 0, 146, 92, 255, 255 # 146.92.255.255
.word 1, 147, 163, 255, 255 # 147.163.255.255
.word 2, 201, 88, 88, 90 # 201.88.88.90
.word 3, 182, 151, 44, 56 # 182.151.44.56
.word 4, 24, 125, 100, 100 # 24.125.100.100
.word 5, 146, 163, 140, 80 # 146.163.170.80
.word 6, 146, 163, 147, 80 # 146.163.147.80
.word 10, 201, 88, 102, 80 # 201.88.102.1
.word 11, 148, 163, 170, 80 # 146.163.170.80
.word 12, 193, 77, 77, 10 # 193.77.77.10
.text
.globl main
main:
la $a1, IP_ROUTING_TABLE_SIZE
lw $t9, ($a1)
li $t7, 255 #top limit
li $v0, 4
la $a0, MESSAGE1 #asking for the address
syscall
FIRST:
li $v0, 4
la $a0, MESSAGE2 #first number
syscall
li $v0, 5
syscall
move $t0, $v0 #saving input for later use.
bgt $t0, $t7, thi1 # if greater than 255
blt $t0,$zero, tlo1 # if less than
SECOND:
li $v0, 4
la $a0, MESSAGE3 # second number
syscall
li $v0, 5
syscall
move $t1, $v0 #saving input
bgt $t1, $t7, thi2 #if greater than
blt $t1,$zero, tlo2 #if less than
THIRD:
li $v0, 4
la $a0, MESSAGE4 #third number
syscall
li $v0, 5
syscall
move $t2, $v0 #saving input
bgt $t2, $t7, thi3 #if greater than
blt $t2,$zero, tlo3 #if less than
FOURTH:
li $v0, 4
la $a0, MESSAGE5 #fourth number
syscall
li $v0, 5
syscall
move $t3, $v0 #saving input
bgt $t3, $t7, thi4 #if greater than
blt $t3,$zero, tlo4 #if less than
Address:
li $v0, 4
la $a0, MESSAGE6
syscall
li $v0, 1
move $a0, $t0
syscall
li $v0, 4
la $a0, MESSAGE7
syscall
li $v0, 1
move $a0, $t1
syscall
li $v0, 4
la $a0, MESSAGE7
syscall
li $v0, 1
move $a0, $t2
syscall
li $v0, 4
la $a0, MESSAGE7
syscall
li $v0, 1
move $a0, $t3
syscall
li $v0, 4
la $a0, MESSAGE14
syscall
j ClassSort
P_EXIT:
li $v0, 4
la $a0, MESSAGE13
syscall
jr $31 #end of module main
################################################################
ClassSort:
#check for class A
li $t5, 127
blt $t0, $t5, ClassA
#check for class B
li $t5, 191
blt $t0, $t5, ClassB
#check for class C
li $t5, 223
blt $t0, $t5, ClassC
#check for class D
li $t5, 239
blt $t0, $t5, ClassD
#Invalid otherwise
bgt $t0, $t5, Invalid
thi1:
li $v0, 4
la $a0, ERROROVER #too High
syscall
j FIRST
tlo1:
li $v0, 4
la $a0, ERRORUNDER #too Low
syscall
j FIRST
thi2:
li $v0, 4
la $a0, ERROROVER #too High
syscall
j SECOND
tlo2:
li $v0, 4
la $a0, ERRORUNDER #too Low
syscall
j SECOND
thi3:
li $v0, 4
la $a0, ERROROVER #too High
syscall
j THIRD
tlo3:
li $v0, 4
la $a0, ERRORUNDER #too Low
syscall
j THIRD
thi4:
li $v0, 4
la $a0, ERROROVER #too High
syscall
j FOURTH
tlo4:
li $v0, 4
la $a0, ERRORUNDER #too Low
syscall
j FOURTH
ClassA:
li $v0, 4
la $a0, MESSAGE8
syscall
li $t5, 0 #reset offset
li $t6, 0 #reset counter
ALOOP:
la $a0, IP_ROUTING_TABLE #load table
add $a0, $a0, $t5 #add current offset
lw $s0, ($a0) #load words at offsets
lw $s1,4($a0)
lw $s2,8($a0)
lw $s3,12($a0)
lw $s4,16($a0)
beq $t0, $s1, LINENUMBER #branch if match
addi $t5, 20 #increment offset
addi $t6, 1 #increment counter
beq $t6, $t9, NOMAT
j ALOOP
ClassB:
li $v0, 4
la $a0, MESSAGE9
syscall
li $t5, 0 #reset offset
li $t6, 0 #reset counter
BLOOP:
la $a0, IP_ROUTING_TABLE #load table
add $a0, $a0, $t5 #add current offset
lw $s0, ($a0) #load words at offsets
lw $s1,4($a0)
lw $s2,8($a0)
lw $s3,12($a0)
lw $s4,16($a0)
addi $t5, 20 #increment offset
addi $t6, 1 #increment counter
beq $t0, $s1, MATCHSECOND #branch if match
beq $t6, $t9, NOMAT #branch if no match
j BLOOP
#############################################################
#error is some where here, I think that it is down in MATCHSECOND2
ClassC:
li $v0, 4
la $a0, MESSAGE10
syscall
li $t5, 0 #reset offset
li $t6, 0 #reset counter
CLOOP:
la $a0, IP_ROUTING_TABLE #load table
add $a0, $a0, $t5 #add current offset/ the next line in table
lw $s0, ($a0) #load words at offsets
lw $s1,4($a0)
lw $s2,8($a0)
lw $s3,12($a0)
lw $s4,16($a0)
addi $t5, 20 #increment offset
addi $t6, 1 #increment counter
beq $t0, $s1, MATCHSECOND2 #branch if match
beq $t6, $t9, NOMAT #branch if it reaches the end of the table.
j CLOOP #end of ClassC
####################################################
ClassD:
li $v0, 4
la $a0, MESSAGE11
syscall
j P_EXIT
Invalid:
li $v0, 4
la $a0, MESSAGE12
syscall
j P_EXIT
NOMAT: #no match
li $v0, 4
la $a0, MESSAGE16
syscall
j P_EXIT
LINENUMBER:
li $v0, 4
la $a0, MESSAGE15
syscall
li $v0, 1
move $a0, $s0
syscall
j P_EXIT
MATCHSECOND:
beq $s2, $t1, LINENUMBER
j BLOOP
################################################
#belong to classC/CLOOP
MATCHSECOND2:
beq $s2, $t1, MATCHTHIRD #if second number matches, branch to test third
#if it doesn't match loop back to top
j CLOOP
MATCHTHIRD:
#provide the line of matching address if all three numbers
beq $s3, $t2, LINENUMBER
#if it doesn't match loop back to top
j CLOOP
###############################################
答案 0 :(得分:2)
CLOOP
中(不仅是那里)存在有缺陷的逻辑,当第一个数字为“匹配”而第二个数字为“不匹配”时,将跳过对表大小的检查,因此循环可能IP表数据不足。
其他问题:
#check for class D
li $t5, 239
blt $t0, $t5, ClassD
#Invalid otherwise
bgt $t0, $t5, Invalid
这不包括值240。您可以b Invalid
进行任何测试。
其他一些建议:
如果您保留$ra
(来自main
的返回地址),则可以使用jal subroutine
重用某些通用代码部分,例如thiX
和tloX
代码的一部分..或整个输入值的请求就像一个循环,仅使用参数来显示不同的提示并将值存储在数组中(或单个寄存器,请参见下文)。
IPv4地址是32位值(对于特定值,“ 255”最大的原因),因此被利用。
例如,子网匹配使用掩码,即,如果子网160.120.0.0
(类似于值0xA0780000
)具有掩码255.255.0.0(类似于值0xFFFF0000
),则确定特定的IP abcd是否属于该子网,您可以
is_part_of_subnet = ((IP & mask) == subnetwork_IP);
组装时看起来像
# fake init for example
li $t0, 0xA0780000 # subnet address 160.120.0.0
li $t1, 0xFFFF0000 # subnet mask 255.255.0.0
li $t2, 0x12345678 # some/any IP address
# (must start with 0xA078... to trigger positive match)
# sub-network match-check
# mask-out parts of IP address which are not significant for test
and $t3, $t2, $t1 # this will clear third/fourth value to zero
beq $t3, $t0, IP_is_part_of_sub_network
# IP is not part of subnetwork (first two values are different)
...
IP_is_part_of_sub_network:
...
表中的行号应该是从遍历数组计算得出的值,而不是部分存储值。
将这两件事放在一起后,实际上可以将IP表压缩为每行一个单词,例如:
.word 0x925CFFFF # 146.92.255.255
要使beq
测试正常,您应该使用类掩码屏蔽这两个值,以使IP地址中只有重要部分可以生存下来进行比较...
(我不是网络专家,所以我可能已经翻转了子网掩码定义,也许是0.0.255.255,但是随后代码会根据and
指令的需要翻转掩码,或者将使用这样的掩码,但是使用or
来将较低位置的位值设置为255,从编程的角度来看,您只需确保使用正确的和/或/翻转序列即可正确的结果)