测试一个值是否在两个范围之一内 [英] Testing if a value is within one of two ranges

查看:32
本文介绍了测试一个值是否在两个范围之一内的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个 MIPS 程序,它只能使用大写或小写字符作为输入.我的程序使用字符的 ASCII 值工作.

I am writing a MIPS program that should only works with uppercase or lowercase characters as input. My program works using the ASCII values of the characters.

我需要检查输入中的每个字符是否在 65-90 (A-Z) 或 97-122 (a-z) 的 ASCII 范围内.如果它不在这两个范围内,请跳过此字符并重复下一个字符.如何做到这一点?

I need to check if each character in the input is in the ASCII range of 65-90 (A-Z) or else 97-122 (a-z). If it is not in either of those ranges, skip this character and repeat for the next character. How can this be done?

编辑

这是我刚刚想出的一个解决方案,但我确定有一个不那么丑陋的方法来做到这一点?

Here is a solution I just came up with but I'm sure there is a less ugly way to do this?

function:    #increment $t0 to next char of input
             blt $t0, 65, function
             bgt $t0, 122, function
             blt $t0, 91, continue
             bgt $t0, 96, continue
             j   function
continue:    ...
             j   function

推荐答案

不管你做什么,你都需要四个分支insst.

No matter what you do, you'll need four branch insts.

我要做的第一件事是为每条指令添加侧边栏注释.

The first thing I'd do is add sidebar comments to each instruction.

好的注释是任何语言的一部分,但对于 asm 来说至关重要.几乎每一行都应该有它们.它们解决了您算法的逻辑(即什么/为什么").说明本身就是如何".

Good comments are part of any language, but crucial for asm. Virtually every line should have them. They address the logic of your algorithm (i.e. the "what/why"). The instructions themselves are the "how".

请注意,您对 ASCII 字符使用十进制数字.如果没有注释,就很难按照逻辑判断说明是否正确.

Notice that you're using decimal numbers for the ASCII chars. Without comments it's difficult to follow the logic to determine if the instructions are correct.

我会稍微调整您的分组,以将 A-Z 测试和 a-z 测试放在一起,而不是将它们混合在一起.这可能会稍微慢一些,但代码更直观.

I'd adjust your grouping a bit to keep A-Z tests together and a-z tests together and not intermix them. This might be slightly slower, but the code is more intuitive.

我还做了第三个版本,很容易理解.它使用字符常量而不是硬连线的十进制值.

I also did a third version that is very easy to understand. It uses character constants instead of hardwired decimal values.

这是带注释的原件:

 function:
    # increment $t0 to next char of input

    blt     $t0,65,function         # less than 'A'? if yes, loop
    bgt     $t0,122,function        # greater than 'z'? if yes, loop

    blt     $t0,91,continue         # less than or equal to 'Z'? if yes, doit
    bgt     $t0,96,continue         # greater than or equal to 'a'? if yes, doit

    j       function

continue:
    # ...
    j       function

<小时>

这是重新排序的版本:


Here's the reordered version:

 function:
    # increment $t0 to next char of input

    blt     $t0,65,function         # less than 'A'? if yes, loop
    blt     $t0,91,continue         # less than or equal to 'Z'? if yes, doit

    bgt     $t0,122,function        # greater than 'z'? if yes, loop
    bgt     $t0,96,continue         # greater than or equal to 'a'? if yes, doit

    j       function

continue:
    # ...
    j       function

<小时>

这是最直接的版本.这是最容易理解的,而且就我个人而言,我会这样做.它还消除了额外/无关的 j 指令.

以前的版本必须知道" A-Z 的价值低于 a-z.他们可以摆脱"这一点,因为 ASCII 值是硬连线"的十进制.

The previous versions have to "know" that A-Z is lower in value than a-z. They could "get away" with this because the ASCII values were "hardwired" in decimal.

在 C 语言中,这 [必然] 不是一个好主意(即您将使用字符常量).mips 汇编器允许字符常量,因此以下内容实际上是有效的:

In C, that wouldn't [necessarily] be a good idea (i.e. you'd use the character constants). mips assemblers allow character constants, so the following is actually valid:

 function:
    # increment $t0 to next char of input

    blt     $t0,'A',trylower        # less than 'A'? if yes, try lowercase
    ble     $t0,'Z',continue        # less than or equal to 'Z'? if yes, doit

trylower:
    blt     $t0,'a',function        # less than 'a'? if yes, loop
    bgt     $t0,'z',function        # greater than 'z'? if yes, loop

continue:
    # ...
    j       function

有一句古老的格言:先把它做好,然后再让它变得更快(来自 Brian Kernighan 和 P.J. Plauger 的编程风格元素")

There's an old maxim: Make it right before you make it faster (From "Elements of Programming Style" by Brian Kernighan and P.J. Plauger)

这是一个构建查找表的额外版本.预构建它需要更多时间,但实际循环更快.

Here's an extra version that builds a lookup table. It takes a bit more to pre-build it, but the actual loop is faster.

在各种版本中,bltbgt 是生成 sltibne 的伪操作addi,slti,bne 分别.所以,我们实际上是在谈论 10 条指令,而不仅仅是 4 条.

In the various versions blt and bgt are pseudo ops that generate slti,bne and addi,slti,bne respectively. So, we're really talking about 10 instructions and not just 4.

因此,为了获得更简单/更快的循环,表构建可能是值得的.

So, the table build may be worth it to get a simpler/faster loop.

    .data
isalpha:    .space  256

    .text
main:
    la      $s0,isalpha             # get address of lookup table

    li      $t0,-1                  # byte value
    li      $t2,1                   # true value

    # build lookup table
build_loop:
    # increment $t0 to next char of input
    addi    $t0,$t0,1               # advance to next char
    beq     $t0,256,build_done      # over edge? if so, table done

    blt     $t0,'A',build_lower     # less than 'A'? if yes, try lowercase
    ble     $t0,'Z',build_set       # less than or equal to 'Z'? if yes, doit

build_lower:
    blt     $t0,'a',build_loop      # less than 'a'? if yes, loop
    bgt     $t0,'z',build_loop      # greater than 'z'? if yes, loop

build_set:
    addiu   $t1,$s0,$t0             # point to correct array address
    sb      $t2,0($t1)              # mark as a-z, A-Z
    j       build_loop              # try next char

build_done:

function:
    # increment $t0 to next char of input

    addu    $t1,$s0,$t0             # index into lookup table
    lb      $t1,0($t1)              # get lookup table value
    beqz    $t1,function            # is char one we want? if no, loop

continue:
    # ...
    j       function

<小时>

这是一个带有预定义查找表的版本:


Here's a version with a predefined lookup table:

    .data
isalpha:
    .byte   0:65
    .byte   1:26
    .byte   0:6
    .byte   1:26
    .byte   0:133

    .text
    la      $s0,isalpha             # get lookup table address

function:
    # increment $t0 to next char of input

    addu    $t1,$s0,$t0             # index into lookup table
    lb      $t1,0($t1)              # get lookup table value
    beqz    $t1,function            # is char one we want? if no, loop

continue:
    # ...
    j       function

这篇关于测试一个值是否在两个范围之一内的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆