如何在Assembly中的某个位置将字符串插入其他字符串?

时间:2016-05-10 09:37:25

标签: assembly x86 masm irvine32

对于我的任务,我试图编写像C ++插入一样的插入函数。 我的函数应该将一个字符串插入到某个位置的其他字符串中。

输入

Be my good friend today

输出

Insert PROC PROC uses edi esi ebx ecx,
                  destination:DWORD ,
                  source:DWORD,
                  position:DWORD

    mov  esi,destination          ;add esi address of str
    add  esi,position
    add  esi,4                     ;lenght of source
    mov  edi,destination           
    add  edi,position

    ;I don't know what should I do in here

    ;How should I make room in the middle of destination ?
    ;How should I insert at certain position + source length :-(
    ;Also, I shouldn't use loop and lea. 


    rep  movsb

    Insert ENDP
  

我应该如何在琴弦的中间腾出空间?

到目前为止,这是我的代码。

CONSTRAINT [FK_T_Stanje_T_Artikli] 
FOREIGN KEY ([StanjeId]) 
REFERENCES [dbo].[T_Artikli] ([ArtikliId])

4 个答案:

答案 0 :(得分:3)

我将避免提供任何代码,因为我无意为您编写任务,但我会尝试解释您将如何完成它。

我将假设以下内容:

1)destination在其地址处有足够的内存来保存已完成的字符串而不会覆盖任何其他变量。

2)您实际上想要插入"good "(带有尾随空格),而不是"good",因为如果您插入"good",最终会导致"Be my goodfriend today" (没有好人和朋友之间的空间)。

3)你实际上打算指定位置5而不是位置6,因为C ++ insert使用从零开始的位置(位置0是第一个字符,位置1是第二个,等等)。

您的第一步是复制字符串的右侧部分以腾出空间。您将从插入的起始位置复制字符到起始位置加上要插入的字符串的大小,最后是以下内容:

destination : Be my frienfriend today

这里有一个问题:您必须从destination的末尾复制向后以避免覆盖尚未复制的字符 - 如果您从偏移量6开始并且复制到偏移11,你将覆盖需要首先复制到偏移16的偏移11的值,你最终会得到这样的结果:

destination : Be my frienfrienfrienfri

通过向后复制,可以避免这个问题。使用适当的decsub运算符进行简单的条件跳转可以正常工作。

在为上面指定的源字符串腾出空间之后,可以正确加载寄存器并使用rep movsb将源复制到指定位置的目标位置,覆盖已复制的字符。

由此,destination将包含"Be my good friend today"

答案 1 :(得分:0)

你应该为新的"字符串预留内存"长度为og的原始字符串+要插入的字符串的长度。从源字符串中复制下一个字符,直到指定的位置(根据字符宽度使用LODSB或LODSW)。指向新输出字符串并将edi指向源数组。将CX设置为位置值。这会将字符从源复制到新的目标内存。然后将edi指向要插入的字符串,并将cx设置为要插入的字符串的长度。再次运行LODSW,最后将edi指向源字符串的位置,并将cx设置为源字符串的长度减去位置,并最后运行lodsw。

答案 2 :(得分:0)

到新字符串:

从原件复制字符,然后复制新字符,然后复制原件的尾部。

在就地:

复制字符串的尾部以创建一个间隙来存储新字符串。这就像memmove:由于副本的来源和目的地重叠,您应该从最后一个字符开始,这样您就不会覆盖尚未复制的字符。它也与InsertionSort's copying to make room for a new element相同。

您可能想要使用两个寄存器来跟踪源位置和目的地位置。

答案 3 :(得分:0)

您的问题可以通过两个函数来解决:第一个函数将字符串的字符从SI位置开始向右移位一个位置,第二个函数将第一个函数调用第一个CX次。这些函数是腾出空间来插入新字符串所必需的(我想你可以将它们合并到一个函数中)。之后,使用源字符串覆盖目标字符串很容易。我选择" $"要完成字符串,您可以用零或其他方式更改它:

<强> shift_right_once

;---------------------------------------------------
;SHIFTS ONE POSITION TO THE RIGHT ALL THE CHARACTERS
;OF A STRING STARTING AT POSITION POINTED BY "SI".
;STRING MUST FINISH WITH "$".
;EXAMPLE: SI = 6
;      INPUT = 'Be my friend today$$$$$$$$$$$$$$$$'
;     OUTPUT = 'Be my ffriend today$$$$$$$$$$$$$$$'
;MODIFIED REGISTERS : AX, SI.

shift_right_once proc   
    mov  al, [ si ]    ;FIRST CHAR TO START PROCESS.
shifting:
    cmp  al, '$'       
    je   end_shifting  ;IF ( END OF STRING )
    inc  si
    mov  ah, [ si ]
    mov  [ si ], al
    xchg al, ah
    jmp  shifting
end_shifting:    
    ret
shift_right_once endp

<强> shift_right_cx

;---------------------------------------------------
;SHIFTS "CX" POSITIONS TO THE RIGHT ALL THE CHARACTERS
;OF A STRING STARTING AT POSITION POINTED BY "SI".
;STRING MUST FINISH WITH "$".
;EXAMPLE: SI = 6
;         CX = 3
;      INPUT = 'Be my friend today$$$$$$$$$$$$$$$$'
;     OUTPUT = 'Be my ffffriend today$$$$$$$$$$$$$'
;MODIFIED REGISTERS : AX, CX.

shift_right_cx proc
    push si
    call shift_right_once      ;CALL PREVIOUS FUNCTION.
    pop  si
    loop shift_right_cx    
    ret
shift_right_cx endp

下一个小程序(用EMU8086制作)展示了如何使用它们:

.stack 100h

.data

destination db 'Be my friend today$$$$$$$$$$$$$$$$'
source      db 'good $'
length      dw 5             ;LENGTH OF "SOURCE".
position    dw 6             ;POSITION TO INSERT.

.code
    mov  ax, @data
    mov  ds, ax    
    mov  es, ax    

;SHIFT CHARS TO THE RIGHT TO MAKE ROOM FOR NEW STRING.
    mov  cx, length           ;HOW MANY CHARS TO PUSH.
    mov  si, offset destination
    add  si, position
    call shift_right_cx

;OVERWRITE OLD CHARS WITH THE NEW ONES.
    mov  cx, length           ;HOW MANY NEW CHARS.
    mov  di, si               ;DI = DESTINATION.
    mov  si, offset source    ;SI = SOURCE.
    rep  movsb                ;DO { [DI]=[SI] } WHILE CX>0.

;WAIT FOR A KEY.
    mov  ah, 0
    int  16h        

;FINISH PROGRAM.    
    mov  ax, 4c00h
    int  21h        

;---------------------------------------------------
;SHIFTS "CX" POSITIONS TO THE RIGHT ALL THE CHARACTERS
;OF A STRING STARTING AT POSITION POINTED BY "SI".
;STRING MUST FINISH WITH "$".
;EXAMPLE: SI = 6      |
;         CX = 3
;      INPUT = 'Be my friend today$$$$$$$$$$$$$$$$'
;     OUTPUT = 'Be my ffffriend today$$$$$$$$$$$$$'
;MODIFIED REGISTERS : AX, CX.

shift_right_cx proc
    push si
    call shift_right_once ;SHIFT RIGHT CHARACTERS ONCE.
    pop  si
    loop shift_right_cx    
    ret
shift_right_cx endp

;---------------------------------------------------
;SHIFTS ONE POSITION TO THE RIGHT ALL THE CHARACTERS
;OF A STRING STARTING AT POSITION POINTED BY "SI".
;STRING MUST FINISH WITH "$".
;EXAMPLE: SI = 6      |
;      INPUT = 'Be my friend today$$$$$$$$$$$$$$$$'
;     OUTPUT = 'Be my ffriend today$$$$$$$$$$$$$$$'
;MODIFIED REGISTERS : AX, SI.

shift_right_once proc   
    mov  al, [ si ]    ;FIRST CHAR TO START PROCESS.
shifting:
    cmp  al, '$'       
    je   end_shifting  ;IF ( END OF STRING )
    inc  si
    mov  ah, [ si ]
    mov  [ si ], al
    xchg al, ah
    jmp  shifting
end_shifting:    
    ret
shift_right_once endp

希望这会对你有所帮助。

相关问题