Tasm:尝试将相反顺序的字符串复制到另一个字符串并使用字符串操作

时间:2018-05-06 05:36:38

标签: assembly tasm

您好我正在尝试从用户逐个字符获取字符串,然后将该字符串的反向存储在未初始化的变量中。在我想要显示未初始化的变量之后。我知道还有其他方法可以使用但我希望使用字符串操作我认为std指令可以用来以相反的顺序遍历字符串。我知道cld用于从左到右设置顺序。我还检查了教科书,并在使用后使用std和popf之前说了pushf。如果是这种情况,则应该放置推送和弹出的位置。

  INCLUDE   PCMAC.INC
                .MODEL SMALL
                .386
                .STACK 128
;================================================
                .DATA
prompt1         DB          13, 10,'Enter a character(Press ENTER to end Expression): $'
prompt2         DB          'Are you done ?:    $'
prompt3         DB          13, 10,'Not valid choice try again', 13, 10,'$'     
userExp         DB          50 DUP (?)
bwUserExp       DB          50 DUP (?)      
validity        DB          'Invalid$','Valid$'         
;================================================               
                .CODE
                EXTRN       PutStr : NEAR, GetCh : NEAR, PutCh : NEAR
Main            PROC        NEAR
                mov         ax, @DATA
                mov         ds, ax
                mov         es, ax
                xor         bx, bx              ;Clears bx register
                xor         cx, cx              ;Clears cx register

DispPrompt:     _PutStr     prompt1             ;Displays prompt1 to screen

GetEXP:         _GetCh      al                  ;Gets character from user
                cmp         al, 13              ;Compares character 
                                                ;to Carriage return 
                je          LoadUserExp         ;If equal to the carriage
                                                ;return user jumps to
                                                ;LoadUserExp 
                cmp         al, 97              ;Compares character to a 
                jge         AddtoExp            ;If equal or greater than
                                                ;a user jumps to AddtoExp
                cmp         al, 122             ;Compares character to z 
                jle         AddtoExp            ;If equal or greater than
                                                ;a user jumps to AddtoExp
                jmp         GetEXP              ;Jumps to GetEXP if character 
                                                ;is not any of the matching
                                                ;characters

AddtoExp:       mov         userExp + bx, al    ;Adds character from 
                                                ;al to userExp array    
                inc         bx                  ;increments bx to
                                                ;increment the position
                                                ;in the array
                jmp         GetEXP              ;Jumps to GetEXP

LoadUserExp:    
                mov         si, OFFSET userExp      ;Loads userExp into si
                mov         di, OFFSET bwUserExp    ;Loads bwUserExp into di
                std                                 ;Tells the program to
                                                    ;go from Right to the Left
                mov         cx, bx                  ;Moves bx (the size of the array) into cx
                rep         movsb                   ;Moves the contents of si into di

DispLoop:       
                mov         cx, bx                  ;Moves bx (the size of the array) into cx
                xor         bx, bx                  ;Clears the bx register

DisplayExp:     mov         al, bwUserExp + bx      ;Moves the character 
                                                    ;in position bx into al
                _PutCh      al                      ;Displays the value of
                                                    ;al to the screen
                inc         bx                      ;increments bx to increment 
                                                    ;the position in the array
                dec         cx                      ;Decrements cx 
                jcxz        done                    ;Jumps to done if
                                                    ;cx is zero
                jmp         DisplayExp              ;Jumps to DisplayExp 
                                                    ; if cx is not zero

done:           mov         ax, 4c00h
                int         21h             

Main            ENDP                            
;================================================
END             Main            

1 个答案:

答案 0 :(得分:1)

您的代码显示了几个问题,但让我们关注“字符串” 指令。

关于DF(方向标志)

cld会将FLAGS寄存器中的DF设置为零。 std会将DF设置为1。

pushf建议的目的是保留原始的DF值,即pushf + popf封闭对应该围绕整个操作,在那里修改DF,以保留原始值,如果您的代码是唯一运行的代码,而不是从外部函数调用,则可以决定不关心原始DF。

在x86调用约定中,通常决定DF预期为零,然后您不需要保留原始值,只需要在代码的每个部分之后清除DF,这需要DF = 1,在调用其他子程序之前。这种约定通常很有效,因为在极少数情况下你需要DF = 1.

关于movs反向字符串

movs[b/w/d]将从[ds:si]加载值并将其存储到[es:di],然后通过添加(sidi来调整++si--di当DF = 0)元素大小或减去(DF = 1)元素大小时。

所以你无法做movsbdi,这需要在指令中间翻转DF。 movsb因此不适合您的需求。

除此之外,您正在使用缓冲区开头的地址加载userExp,因此即使bwUserExp可以执行您想要的操作,也会覆盖 mov si, OFFSET userExp ; source buffer lea di, [bx + bwUserExp - 1] ; end(!) of destination buffer mov cx, bx ; cx = size of user input reverse_loop: cld ; DF=0 lodsb ; al = one character, ++si std ; DF=1 stosb ; store character, --di dec cx jnz reverse_loop cld ; DF=0 for future use 缓冲区而不是写入结果进入 mov si, OFFSET userExp ; source buffer lea di, [bx + bwUserExp] ; beyond end of destination buffer mov cx, bx ; cx = size of user input reverse_loop: mov al,[si] dec di inc si mov [di],al dec cx jnz reverse_loop ; di points at bwUserExp here 缓冲区。

您可以像这样使用字符串指令:

                ...
                cmp         al, 97              ;Compares character to a 
                jge         AddtoExp            ;If equal or greater than
                                                ;a user jumps to AddtoExp
                cmp         al, 122             ;Compares character to z 
                jle         AddtoExp            ;If equal or greater than
                                                ;a user jumps to AddtoExp
                jmp         GetEXP              ;Jumps to GetEXP if character 
                                                ;is not any of the matching
                                                ;characters

正如你所看到的,它不是最漂亮的代码片段,并且看起来不合理,字符串指令不适合你的任务,你应该在没有它们的情况下完成任务,如下所示:

~

关于代码的其他问题

                ...
                cmp         al, 'a'
                jb          GetEXP              ; ignore characters below 'a'
                cmp         al, 'z'
                ja          GetEXP              ; ignore characters above 'z'
AddtoExp:
                ... valid 'a'..'z' input, add to buffer ...

这允许用户输入例如 dec cx ;Decrements cx jcxz done ;Jumps to done if ;cx is zero jmp DisplayExp ;Jumps to DisplayExp (126)作为有效字符,因为126> = 97.此外,我总是对与ASCII字符一起使用的signed-math分支不满意,因为我认为ASCII字符为无符号,但在技术上不会改变你的情况,因为你只对97..122范围感兴趣,所以输入一些代码大于128的DOS字符(不是常规的ASCII)被视为负值对你好。

您可以修复+简化逻辑:

            dec         cx                      ;Decrements cx 
            jnz         DisplayExp              ;Jumps to DisplayExp until cx is zero

m014.text = [NSString stringWithFormat:@"<html><head><style type='text/css'>body {background-color: transparent;border: 0px;margin: 0px;padding: 0px;font-family: '%@'; font-size: %fpx;;ccolor:;}</style></head><body dir='%@'>%@<style type='text/css'> iframe { width: 100%% !important; } img {width: 100%% !important; height: auto;} table {width: 100%%;}</style></body></html>", localize(@"myFontName"), @16, localize(@"myDir"), m014.text];

m014.attributedText = [[NSAttributedString alloc] initWithData: [m014.text dataUsingEncoding:NSUTF32StringEncoding] options: @{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes: nil error: nil];

......虽然这有效,但你可以做得更简单,更高效:

[m014.text dataUsingEncoding:NSUTF32StringEncoding]