汇编语言:将小写字母转换为大写

3

我有一个任务,描述如下:

- Reads printable characters (20h-7Fh) from the keyboard without echoing
- Uppercase letters are printed to display
- Lowercase letters are converted to uppercase and then printed to display
- Blank spaces and periods are printed to display; everything else is trashed
- Program ends when period is printed

到目前为止,我的程序如下:

    .model      small
    .8086


    .data


    .code

start:
        mov     ax,@data
        mov     ds,ax

read:
        mov     ah,8
        int     21h
        cmp     al,61
        jl      write
        cmp     al,7fh
        jg      read
        sub     al,20h
        jmp     write

write:      cmp     al,20h
        jl      read
        mov     dl,al
        mov     ah,2
        int     21h
        cmp     dl,2eh
        jne     read

exit:
        mov     ax,4c00h
        int     21h
        end     start

我的程序成功将小写字母转换为对应的大写字母并打印出来,但我无法过滤掉其他字符。如何最好地只允许空格、句号和字母通过显示?

看ASCII表,

21h - 2Dh can be trashed
2Fh - 40h can be trashed
5bh - 60h can be trashed
7bh - 7fh can be trashed

有人能帮我想出最佳逻辑来比较这些值的输入,然后丢弃掉那些在上述范围内的值吗?我们的评分标准是效率,编写0-20条指令将被授予满分。我已经写了20条指令,在这里我还没有包括找到垃圾值的比较。

编辑
这是我缩小代码范围后得到的结果:

    .model      small
    .8086


    .data


    .code


read:
        mov     ah,8
        int     21h
        cmp     al,' '
        je      write
        cmp     al,'.'
        je      write
        cmp     al,'a'
        jl      read
        cmp     al,'Z'
        jg      convert

convert:    
        cmp     al,'a'
        jl      read
        sub     al,20h

write:      
        mov     dl,al
        mov     ah,2
        int     21h
        cmp     dl,'.'
        jne     read

exit:
        mov     ax, 4c00h
        int     21h
        end     read

目前有21条指令!我的代码中是否有重复的部分可以去掉,以达到20条指令呢?


为了节省一些指令,你不需要前两个(因为你没有使用ds的指令)。此外,int 20h将会在不需要先设置ax寄存器的情况下退出你的程序。 - Greg Hewgill
@raphnguyen: 不要使用神奇常量,而是使用字面Ascii表示来帮助记录您的意思。例如,cmp al,'a'比您目前写的更易读且有意义。 - wallyk
4个回答

1

我认为你可以通过这样做来节省一些指令:

read:
if lowercase then make uppercase
if uppercase then print
if space then goto print
if period then quit
goto read

print:
do the print
goto read

有什么特别的原因导致了这个踩票吗?我知道这不是他的汇编语言,但翻译很简单。 - corsiKa

0

您可以修改您的逻辑以执行以下操作:

  • 如果是空格或句号,则跳到 write
  • 将小写字母转换为大写字母
  • 如果不是大写字母,则跳回到 read

请注意,“将小写字母转换为大写字母”无需先检查输入是否为字母。只需要使用适当的值作为 xx and 即可(我会让您解决该值)。此步骤还将修改除字母外的字符,但由于下一步是检查是否为字母,因此无关紧要。


维基百科实际上有一个很好的介绍。使用正确的值,您可以将输入字符与该值进行“and”操作,以便大写字符保持不变,小写字符转换为大写。 - Greg Hewgill
感谢您的澄清。我已经手动转换了一些小写字母和大写字母,并比较了“and”。我看到它们都相差32个十进制位,但我仍然困惑如何使用这个“and”。我似乎想不出一个值,可以使大写字符保持不变,同时将小写字符转换为大写。我确实看到,“and”大写和小写的等效结果是大写字母。 - raphnguyen
考虑到32十进制是0x20十六进制,它们在特定位置上只有一个比特位的差异。思考如何使用“and”运算符来将单个比特位强制为您想要的值(使字符大写)。一次考虑一个比特位的位置。 - Greg Hewgill
抱歉,我好像不太明白。如果我执行 'and 20h,97h',结果应该是20h,对吗?这对于所有小写字母都是正确的,那么如果是这样,我需要调用其他什么来打印大写字母的等价物吗? - raphnguyen
你对于0x20的值非常接近,但你想要的是它的相反数。你想要保留所有位,除了你想要关闭的那一位。(我希望当你理解这个时会有一个“啊哈!”的时刻。随着你在学习中的进展,位运算将变得非常重要。) - Greg Hewgill
显示剩余5条评论

-1

标题 示例汇编代码结构 .MODEL SMALL .STACK .DATA

MSG1            DB     "输入一个字母:$" MSG2            DB     10, "大写字母是:$" MSG3            DB     10,"[按任意键继续] $"

.CODE         MOV AX,@DATA         MOV DS,AX         MOV ES,AX balik:         MOV AX,3         INT 10H

; --------------------你的代码执行从这开始-------------------------

MOV AH,9 LEA DX,MSG1 INT 21H

MOV AH,1 INT 21H

AND AL,00DFH

MOV AH,9 LEA DX,MSG2 INT 21H

MOV AH,2 MOV DL,AL INT 21H

MOV AH,9 LEA DX,MSG3 INT 21H

MOV AH,1 INT 21H

MOV BL,AL

CMP BL,27 JE TAPOS JMP balik

TAPOS:

;-------------------------------代码结束---------------------------------- MOV AH,4CH INT 21H END


请格式化您的回答并添加一些解释。 - Alexei - check Codidact

-1
我会设置一个表格来对应值20..7f,为每个范围设置标志,并稍后使用每个输入字节-20h作为索引进入表格。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接