从汇编nasm中的5个字符串中插入字符



我必须编写一个汇编程序,从用户在键盘上键入的五个不同字符串中插入字符,例如,如果我有:

  • S1: "Hello">
  • S2: "Bye">
  • S3: "Apple">
  • S4: "Car">
  • S5: "Tree">

结果为:" hbacteyparlepreloe">

这就是我目前所做的,它可以从相同大小的字符串中插入,我不知道该怎么做才能让它对不同大小的字符串起作用,如果有更好的方法。我将非常感谢你的帮助,因为这是我的第一个汇编程序之一。

segment .data
instruccion db 'Ingrese 5 cadenas de igual longitud no mayores a 20 caracteres:',0x0A
lonI EQU ($-instruccion)
segment .bss
contador resb 1
cad1 resb 20
cad2 resb 20
cad3 resb 20
cad4 resb 20
cad5 resb 20
cad6 resb 101
segment .text
global _start
_start:
mov edx,lonI
mov ecx,instruccion
call imprimir
mov edx,20d
mov ecx,cad1
call leer
mov ecx,cad2
call leer
mov ecx,cad3
call leer
mov ecx,cad4
call leer
mov ecx,cad5
call leer
mov edi,cad1
mov ecx,255
mov eax,0Ah
repne scasb
mov eax,255
inc ecx
sub eax,ecx
mov edi,cad6
mov ecx,eax
mov ebx,0
ciclo:
mov esi,cad1
cld
mov edx,ecx
mov ecx,ebx
cmp ebx,0
jne THEN1
je ELSE1
THEN1:
lodsb
loop THEN1
ELSE1:
movsb
mov esi,cad2
cld
mov ecx,ebx
cmp ebx,0
jne THEN2
je ELSE2
THEN2:
lodsb
loop THEN2
ELSE2:
movsb
mov esi,cad3
cld
mov ecx,ebx
cmp ebx,0
jne THEN3
je ELSE3
THEN3:
lodsb
loop THEN3
ELSE3:
movsb
mov esi,cad4
cld
mov ecx,ebx
cmp ebx,0
jne THEN4
je ELSE4
THEN4:
lodsb
loop THEN4
ELSE4:
movsb
mov esi,cad5
cld
mov ecx,ebx
cmp ebx,0
jne THEN5
je ELSE5
THEN5:
lodsb
loop THEN5
ELSE5:
movsb
mov ecx,edx
inc ebx
loop ciclo
mov eax,0Ah
stosb
mov edx,101d
mov ecx,cad6
call imprimir
mov eax,1           ;system call number (sys_exit)
int 0x80            ;call kernel
leer:
mov ebx,0
mov eax,3
int 0x80
ret
imprimir:
mov ebx,1
mov eax,4
int 0x80
ret

结果:"HBACTeyparleprelloe"

我当然希望这是一个打字错误,否则这将成为一个非常讨厌的练习!我将假设"HBACTeyparleprelleoe" .

它可以插入具有相同大小的string

你现在的代码似乎做正确,但为什么它是如此复杂?
如果当前索引(字符串中的偏移量)为0,则只执行movsb。如果当前索引不是0,那么你需要跳过,你可以使用(浪费的)loop/lodsb指令来完成。有时人们想知道为什么rep lodsb是允许的,这里他们有一点用例。虽然不是真的,因为实际的解决方案是替换:

mov esi,cad1
cld
mov ecx,ebx
cmp ebx,0
jne THEN1
je ELSE1
THEN1:
lodsb
loop THEN1
ELSE1:
movsb

完全由:

lea     esi, [cad1 + ebx]
movsb

或者:

movzx   eax, byte [cad1 + ebx]
stosb

我不知道该怎么做才能使不同大小的字符串

下面我将给出三个解决方案,都经过测试。

解决方案1

因为精确地有5个输入字符串,32位x86架构有适当数量的寄存器来将单个指针保存在自己的寄存器中。这种方法给出了最快的代码,但前提是每个字符串的长度相差不太大。

S:      db      43 dup 0
S1:     db      "Hello", 10
S2:     db      "Bye", 10
S3:     db      "AppleADayKeepsTheDoctorAway", 10
S4:     db      "Car", 10
S5:     db      "Tree", 10
...
Begin:  mov     ebx, S1                 ; Addresses of the input strings
mov     ecx, S2
mov     edx, S3
mov     esi, S4
mov     edi, S5
mov     ebp, S                  ; Address of the output string
.a:     push    ebp                     ; (1)
movzx   eax, byte [ebx]         ; Read a character from this string
cmp     al, 10                  ; If this string is exhausted, then
je      .b                      ;  no longer add to the output string
inc     ebx                     ; Go to the next character in this string
mov     [ebp], al               ; Add character to the output string
inc     ebp
.b:     movzx   eax, byte [ecx]         ; Read a character from this string
cmp     al, 10                  ; If this string is exhausted, then
je      .c                      ;  no longer add to the output string
inc     ecx                     ; Go to the next character in this string
mov     [ebp], al               ; Add character to the output string
inc     ebp
.c:     movzx   eax, byte [edx]         ; Read a character from this string
cmp     al, 10                  ; If this string is exhausted, then
je      .d                      ;  no longer add to the output string
inc     edx                     ; Go to the next character in this string
mov     [ebp], al               ; Add character to the output string
inc     ebp
.d:     movzx   eax, byte [esi]         ; Read a character from this string
cmp     al, 10                  ; If this string is exhausted, then
je      .e                      ;  no longer add to the output string
inc     esi                     ; Go to the next character in this string
mov     [ebp], al               ; Add character to the output string
inc     ebp
.e:     movzx   eax, byte [edi]         ; Read a character from this string
cmp     al, 10                  ; If this string is exhausted, then
je      .f                      ;  no longer add to the output string
inc     edi                     ; Go to the next character in this string
mov     [ebp], al               ; Add character to the output string
inc     ebp
.f:     pop     eax                     ; (1)
cmp     eax, ebp                ; Was anything added to the output string ?
jne     .a                      ; Yes, then repeat

解决方案2

一个小编辑允许我们处理任意数量的输入字符串。这种方法比以前慢,但它需要填充字符串以使它们具有相同的长度(就像您在问题中遇到的那样)。

S:      db      43 dup 0
S1:     db      "Hello", 22 dup 10, 10
S2:     db      "Bye", 24 dup 10, 10
S3:     db      "AppleADayKeepsTheDoctorAway", 10
S4:     db      "Car", 24 dup 10, 10
S5:     db      "Tree", 23 dup 10, 10
...
Begin:  xor     ebx, ebx                ; Current offset in every string
mov     ebp, S                  ; Address of the output string
.a:     push    ebp                     ; (1)
movzx   eax, byte [S1 + ebx]    ; Read a character from this string
cmp     al, 10                  ; If this string is exhausted, then
je      .b                      ;  no longer add to the output string
mov     [ebp], al               ; Add character to the output string
inc     ebp
.b:     movzx   eax, byte [S2 + ebx]    ; Read a character from this string
cmp     al, 10                  ; If this string is exhausted, then
je      .c                      ;  no longer add to the output string
mov     [ebp], al               ; Add character to the output string
inc     ebp
.c:     movzx   eax, byte [S3 + ebx]    ; Read a character from this string
cmp     al, 10                  ; If this string is exhausted, then
je      .d                      ;  no longer add to the output string
mov     [ebp], al               ; Add character to the output string
inc     ebp
.d:     movzx   eax, byte [S4 + ebx]    ; Read a character from this string
cmp     al, 10                  ; If this string is exhausted, then
je      .e                      ;  no longer add to the output string
mov     [ebp], al               ; Add character to the output string
inc     ebp
.e:     movzx   eax, byte [S5 + ebx]    ; Read a character from this string
cmp     al, 10                  ; If this string is exhausted, then
je      .f                      ;  no longer add to the output string
mov     [ebp], al               ; Add character to the output string
inc     ebp
.f:     inc     ebx                     ; Go to next character in every string
pop     eax                     ; (1)
cmp     eax, ebp                ; Was anything added to the output string ?
jne     .a                      ; Yes, then repeat

3

解决方案这一次,我们创建了一个数组,其中包含指向各个字符串的指针。这些指针依次用于从关联的字符串中检索字符,当遇到字符串结束标记(10)时,只需从数组中删除相关指针。其他解决方案继续处理耗尽的字符串,但是这里耗尽的字符串从循环中消失。
因为这个方法有更多的内务工作要做,所以它在非常常规的测试数据上运行得比较慢。然而,一旦你给它一个更现实的数据集,一个短字符串和长字符串,它会发光…对输入字符串的数量也没有限制,不需要填充,也不需要使用相同大小的字符串缓冲区(就像在你的程序中一样)。
P:      dd      S1, S2, S3, S4, S5, 0
S:      db      43 dup 0
S1:     db      "Hello", 10
S2:     db      "Bye", 10
S3:     db      "AppleADayKeepsTheDoctorAway", 10
S4:     db      "Car", 10
S5:     db      "Tree", 10
...
Begin:  mov     ebp, S                  ; Address of the output string
jmp     .e
.a:     mov     edi, ebx
.b:     mov     eax, [edi+4]            ; Move all the stringpointers that follow
mov     [edi], eax              ;  one position down in the array
add     edi, 4
test    eax, eax                ; Until the zero-terminator got moved down
jnz     .b
jmp     .d                      ; Continue with the next stringpointer
.c:     movzx   eax, byte [esi]         ; Read a character from the current string
cmp     al, 10                  ; If this string is exhausted, then
je      .a                      ;  go remove its pointer from the array
inc     esi                     ; Go to the next character in the current string
mov     [ebx], esi              ; Update the current stringpointer
add     ebx, 4                  ; Go to the next stringpointer
mov     [ebp], al               ; Add character to the output string
inc     ebp
.d:     mov     esi, [ebx]              ; Get current stringpointer
test    esi, esi                ; Arrived at the end of the array if ESI is zero
jnz     .c
.e:     mov     ebx, P                  ; Address of the array with stringpointers
mov     esi, [ebx]              ; Get current stringpointer
test    esi, esi                ; The array is empty if the 1st dword is zero
jnz     .c
0.4µsec0.1µsec5个短字符串2.0µsec2.1µsec1.5µsec

相关内容

  • 没有找到相关文章

最新更新