通过对两个字符串的字符求和/减去来创建一个新数组

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过对两个字符串的字符求和/减去来创建一个新数组相关的知识,希望对你有一定的参考价值。

从2个字节数组开始,S1和S2,应该创建第三个数组,基于以下规则:在偶数位置应该是S1和S2的特定字符的总和,在奇数位置应该是差异的来自S1和S2的特定字符

例:

; S1:1,2,3,4

; S2:5,6,7,8

; D:6,-4,10,-4

我尝试以下面的方式实现它,基于2“for循环”,但经过多次尝试,我发现它可能永远不会工作,因为它们不是同时的。我已经考虑过只使用一个并基于比较来创建总和或差异。事情是,我不太确定应该如何比较(cmp si,?)。任何有关这方面的建议将不胜感激。

ASSUME cs:text_,ds:data_

data_ SEGMENT

s1 db '1','2','3','4'
l equ $-s1 
s2 db '5','6','7','8'
d db l dup (?)

data_ ENDS

text_ SEGMENT
start:
mov ax, data_
mov ds, ax
mov es, ax
mov si, offset s1
mov bx, offset s2
mov di, offset d  
cld
mov cx, l 
jcxz endi

xor cx,cx   ; cx-register is the counter, set to 0
loop1:
    lodsb    ;current character of s1 is stored in al
    add al, byte ptr es:[bx] ;the character of s2, which is on the same position as the one stored in al, is added to al
    stosb   ;data from al is moved to di
    add cx, 2   ;cx is incremented
    cmp cx,l    ; Compare cx to the limit
jl loop1   ; Loop while less 

mov al, 0   ; al is emptied
mov cx, 1   ; cx-register is the counter, set to 1
loop2:
    lodsb   ;current character of s1 is stored in al
    sub al, byte ptr es:[bx] ;the character of s2, which is on the same position as the one stored in al, is added to al
    stosb  ;data from al is moved to di
    add cx, 2 ;Increment
    cmp cx,l    ; Compare cx to the limit
jle loop2   ; Loop while less or equal

endi:
   mov ax, 4c00h
   int 21h
text_ ENDS
end start   

在此先感谢,并对任何错误/不便表示歉意。

答案

正如@Jester指出的那样,双循环可以工作,这只是我如何做的一个例子。然而,这个例子具有破坏性,因为s1的内容正在被修改。如果您想使用此模型,但修改为完全符合您的示例,则修改应该非常容易概念化。

    ASSUME cs:text_,ds:data_

        data_ SEGMENT
    s1 db '1','2','3','4'
    s2 db '5','6','7','8'
        data_ ENDS

        text_ SEGMENT
    start:
            mov     ax, data_
            mov     ds, ax
            mov     es, ax

            mov     si, offset s1
            mov     di, offset s2
            mov     cx, di
            sub     cx, si              ; Now you have the number of entries in CX
            xor     bx, bx
            jcxz    endi

        Next:   
            lodsb
            mov     ah, [di]
            bt      bx, 0               ; Is bit on, then we want to subtract
            jnc     @F - 2
            sub     al, ah
            jmp     @F
            add     al, ah

     @@:    stosb
            xor     bl, 1               ; Toggle add or subtract indicator
            loop    Next

        endi:
            mov     ax, 4c00h
            int     21h

        text_ ENDS
    end start   

注意:我使用NASM,所以希望这个例子适用于MASM

另一答案

代码存在一些问题。

  1. 您无法添加或减去字符。字符不会存储为数字,而是存储为ASCII码。您可以将ASCII代码想象为监视器的命令以显示特定字符​​。处理器需要另一种格式来将其作为整数处理。你必须转换它(如果你想显示它,则返回)。角色的ASCII部分是高半字节。要获得整数删除它(AND 0FhSUB 48)。要获取字符,请将ASCII部分添加到整数(OR 30hADD 48)。梯子是你的家庭作业的主要部分,因为处理负号和数字超过一位数有点挑战。
  2. 使用2循环解决方案,SI,DI和BX必须增加2。 LODSBSTOSB只增加1.因此,您为该寄存器添加了额外的增量。你忘了增加BX。
  3. 这没关系,但是...... JLJLE进行了签名比较。 CX不太可能变为负面。所以把它改成未签名的camparisons JBJBE

以下代码将结果存储为d中的整数:

ASSUME cs:text_,ds:data_

data_ SEGMENT

s1 db '1','2','3','4'
l equ $-s1
s2 db '5','6','7','8'
d db l dup (?)

data_ ENDS

text_ SEGMENT
start:
mov ax, data_
mov ds, ax
mov es, ax
mov si, offset s1
mov bx, offset s2
mov di, offset d
cld
mov cx, l
jcxz endi

xor cx,cx                       ; cx-register is the counter, set to 0
loop1:
    lodsb                       ; current character of s1 is stored in al
    mov ah, byte ptr es:[bx]    ; the character of s2, which is on the same position as the one stored in al, is added to al
    and ax, 0F0Fh               ; Remove the ASCII parts in AH and AL
    add al, ah
    stosb                       ; data from al is moved to di
    add bx, 2                   ; Increment
    add si, 1                   ; Increment
    add di, 1                   ; Increment
    add cx, 2                   ; cx is incremented
    cmp cx,l                    ; Compare cx to the limit
;jl loop1                       ; Loop while less
jb loop1                        ; Loop while below

mov si, offset s1 + 1           ; Reinitialize SI, DI and BX at odd indices
mov bx, offset s2 + 1
mov di, offset d + 1
mov cx, 1                       ; cx-register is the counter, set to 1
loop2:
    lodsb                       ; current character of s1 is stored in al
    mov ah, byte ptr es:[bx]    ; the character of s2, which is on the same position as the one stored in al, is added to al
    and ax, 0F0Fh               ; Remove the ASCII parts in AH and AL
    sub al, ah
    stosb                       ; data from al is moved to di
    add bx, 2                   ; Increment
    add si, 1                   ; Increment
    add di, 1                   ; Increment
    add cx, 2                   ; Increment
    cmp cx,l                    ; Compare cx to the limit
;jle loop2                      ; Loop while less or equal
jbe loop2                       ; Loop while below or equal

endi:
   mov ax, 4c00h
   int 21h
text_ ENDS
end start

单循环解决方案中的比较非常简单。想二元!奇数在最右边的位中有1,偶数是0。你可以用1来AND数,得到0(未设置)或1(设置)。 TEST是一个特殊的x86指令,执行AND但只设置标志而不更改寄存器。如果结果不为null - >奇数,则不设置零flage(请参阅JNZ)。

ASSUME cs:text_,ds:data_

data_ SEGMENT

s1 db '1','2','3','4'
l equ $-s1
s2 db '5','6','7','8'
d db l dup (?)

data_ ENDS

text_ SEGMENT
start:
mov ax, data_
mov ds, ax
mov es, ax
mov si, offset s1
mov bx, offset s2
mov di, offset d
cld
mov cx, l
jcxz endi

xor cx,cx                       ; cx-register is the counter, set to 0
loop1:
    lodsb                       ; current character of s1 is stored in al
    mov ah, byte ptr es:[bx]    ; the character of s2, which is on the same position as the one stored in al, is added to al
    and ax, 0F0Fh               ; Remove the ASCII parts in AH and AL
    test cx, 1                  ; Odd?
    jnz odd                     ; Yes -> jump to the subtraction
    even:
    add al, ah
    jmp l2                      ; Skip the subtraction
    odd:
    sub al, ah
    l2:
    stosb                       ; data from al is moved to di
    add bx, 1                   ; Increment
    add cx, 1                   ; cx is incremented
    cmp cx,l                    ; Compare cx to the limit
jbe loop1                       ; Loop while below

endi:
   mov ax, 4c00h
   int 21h
text_ ENDS
end start
另一答案

我已经考虑过只使用一个并基于比较来创建总和或差异。

这就是你用一个循环(你在哪里求和或基于索引值的差异)的方法:

只需使用以下代码替换您的两个循环: -

  mov cl, 2              ; store 2 in cl which is used to check later if the index is even or odd
  loop1:
        lodsb            ; current character of s1 is stored in al
        mov dl, al       ; save al in dl   
        mov ax, si       ; store the value of si in ax
        dec ax           ; since lodsb increments si we have to decrement it to get the current index  
        div cl           ; divide al with cl
        mov al, dl       ; get the stored value from dl to al 
        cmp ah, 0        ; check if remainder is zero (div instruction stores remainder in ah and quotient in al if divisor is 8bit)
        jne oddNum       ; if no then we are at odd position otherwise we are at even position 
        add al, byte ptr es:[bx] 
        jmp continue
        oddNum:
        sub al, byte ptr es:[bx]      ;the character of s2, which is on the same position as the one stored in al, is added to al
        continue:
        stosb                ; data from al is moved to di    
        inc bx               ; increment bx so that it points to next element in s2 
        cmp si,l             ; Compare cx to the limit
    jl loop1                 ; Loop while less 

在上面的代码中,你将根据si寄存器的值(可以是偶数或奇数)进行求和或差值

以上是关于通过对两个字符串的字符求和/减去来创建一个新数组的主要内容,如果未能解决你的问题,请参考以下文章

FCC 中级算法题 对所有的数字求和

如何从json获取数据中对两个或多个值求和

如何对字符串格式的时间数组求和

如何对整数字符串数组求和?

分享JS数组求和与求最大值的方法

对两个N进制字符串求和