输入一个字符串,拉丁文小写字母和大写字母

时间:2018-06-07 16:34:33

标签: assembly x86

输入一个字符串,拉丁文小写字母变成大写字母,其余字符只切换回二进制代码和显示的偶数位数。

输出必须是'CБCBD' 输出就是这个形象 RUN .EXE

本条例

DOSSEG                                    ;segment sequencing directive
.MODEL SMALL                              ;directive of the model of code 
                                           ;and data of the near type
.STACK 200H                               ;a 512-byte stack
.DATA                                     ;start of the data
STRING DB 'c~cbd$'                        ;string
STRING_LENGTH EQU $-STRING                ;string length=6 in this example 
STRING1 DB STRING_LENGTH DUP (?) , '$'    ;another string1,has the same 
                                           ;length
.CODE                                     ;start of the code
MOV AX,@DATA                              ;access to the data segment
MOV DS,AX                                 ;access to the data segment
XOR SI,SI                                 ;SI set to zero
XOR DI,DI                                 ;DI set to zero

MOV CX,STRING_LENGTH                      ;put string length into CX,for 
                                           ;looping 6 times

S:                                        ;breakpoint S

MOV BL,STRING[DI]                         ;remember current element of 
                                            ;string into BL
AND STRING[DI],11100000B                  ;checking if the current element 
                                           ;of string is lowercase
CMP STRING[DI],01100000B                  ;checking if the current element 
                                           ;of string is lowercase
JNE L1                    ;if the current element of string 
                           ;is lowercase is not equal 
                           ; go to the breakpoint L1 otherwise go to inside

XOR BL,00100000B               ;remember current element of string into BL 
                            ; (lowercase letters) convert to capital letters 
MOV STRING1[SI],BL             ;put the current capital letter into string1

ADD SI,2                 ;increment by 2 (because the size of SI is 2 bytes) 
                           ; to go to the next item of string1
ADD DI,2                 ;increment by 2 (because the size of DI is 2 bytes)  
                           ;to go to the next item of string

LOOP S                                ;cycle,go to the breakpoint S

L1:                                   ;breakpoint L1
XOR STRING[DI],01010101B          ;Switch the current element of string back 
                                    ;to only non-even places
MOV AL,STRING[DI]                 ;put the current element into register AL
MOV STRING1[SI],AL                ;put the current element into string1

ADD SI,2                 ;increment by 2 (because the size of SI is 2 bytes) 
                           ; to go to the next item of string1
ADD DI,2                 ;increment by 2 (because the size of DI is 2 bytes)  
                           ; to go to the next item of string

LOOP S                                    ;cycle,go to the breakpoint S

XOR DX,DX                                 ;DX set to zero
LEA DX,STRING1                            ;download executive address
MOV AH,09H                                ;DOS line output function
INT 21H                                   ;display changed characters
MOV AH,4CH                              ;DOS function of program termination
INT 21H                                   ;finish the program
END 

我使用TURBODEBBUGER看看什么是抢夺但是无法找到问题 AFTER RUNNING PROGRAM USING F9

我在谷歌流行搜索,谷歌但无法找到当前的问题。 你可以帮助我解决这个问题吗?

1 个答案:

答案 0 :(得分:3)

我认为你想要的基本上是这样的主循环:

  ... (set DS, etc)
  mov  cx,STRING_LENGTH
  xor  si,si
processString:
  ; si = index of character to process
  ; cx = characters to process
  mov  al,STRING[si]   ; al = source character
  cmp  al,'a'
  jb   not_lowercase_letter
  cmp  al,'z'
  ja   not_lowercase_letter
  ; lowercase letter in AL detected, make it capital
  and  al,11011111B ; clear the 0x20 bit
  jmp  store_final_character
not_lowercase_letter:
  xor  al,01010101B ; flip the bits on odd positions
store_final_character:
  mov  STRING1[si],al
  inc  si
  loop processString
  ... (output result)

您应该从这段代码中学到什么(如果您设法使其成功):

  • 只有在无法避免存储器时才访问存储器,即字符值从STRING加载一次,并写入STRING1一次。从来没有像XOR STRING[SI],55h这样的指令,然后用这样的记忆值进一步操纵。内存访问比仅在寄存器上执行的操作慢得多,因此只要您有多个操作要做,通常最好将值从内存移动到寄存器中,对其进行所有计算,然后存储最终结果回到记忆中。

  • 因为STRING在1:1映射中转换为STRING1(一个输入字符确实产生一个输出字符),我只使用si中的一个索引,而不是{{1}中的两个相同索引} + si

  • 我正好测试拉丁文小写字母(' a'到' z'值范围),你的位掩码测试可能会误认为像{{1}这样的字符}对于小写字母,请参阅ASCII表定义以了解字符的编码方式,并对其中一些字符进行测试计算,以了解它们的结果。

  • 我有循环体开头和结尾的单一代码路径。我使用小写字母代码路径中的di来跳过非小写的中间部分,然后重新加入到存储修改后的字符的共享代码中。这使我免于存储结果和递增索引的重复行以及两条{指令。

  • 使用有意义的标签名称。 jmp并不意味着什么,对其他源代码读者来说,它会变得非常神秘和难以理解。由于IBM PC计算机使用640kB的基本RAM,因此不需要使用短标签来节省内存,就像我们在具有16-64kB RAM的8位计算机上所做的那样,只需将汇编程序+源代码+编译结果安装到内存中相当成就,并且经常将源代码分成几个较小的部分,分别编译,然后在测试它们之前,你必须从内存中删除汇编器和源代码并加载已编译的机器代码。 (这是1988年的声音,今天你有GIGA字节的内存,你将永远不会在你的整个生命中编写足够长的源代码,甚至可以轻微地填充当前的计算机RAM)。因此,如果1988年已经可以使用有意义的标签名称,那么今天也可以使用它们。