代码之家  ›  专栏  ›  技术社区  ›  Katrin

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

  •  0
  • Katrin  · 技术社区  · 7 年前

    从两个字节数组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   
    

    提前感谢,并对任何错误/不便表示抱歉。

    3 回复  |  直到 7 年前
        1
  •  0
  •   Shift_Left    7 年前

    正如@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

        2
  •  0
  •   rkhb    7 年前

    代码有一些问题。

    1. 不能添加或删除 角色 . 字符不是存储为数字,而是存储为ASCII码。您可以将ASCII码想象为监视器显示特定字符的命令。处理器需要另一种格式将其作为整数处理。您必须对其进行转换(如果要显示它,还必须进行转换)。字符的ASCII部分位于高位半字节。要获取整数,请将其删除( AND 0Fh SUB 48 ). 要获取字符,请将ASCII部分添加到整数中( OR 30h ADD 48 ). 阶梯是你家庭作业的主要部分,因为处理负号和一位数以上的数字有点困难。

    2. SI、DI和BX必须使用2循环解决方案增加2。 LODSB STOSB 仅增加1。因此,您必须为该寄存器添加额外的增量。您忘记增加BX。

    3. 这里没关系,但是。。。 JL JLE 表演 签署 比较。CX不太可能变成负值。所以把它改成未签名的camparisons JB JBE .

    下面的代码将结果存储为整数 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。你可以 AND 带1的数字,得到0(未设置)或1(设置)。 TEST 是一条特殊的x86指令,它执行 以及 但只设置标志,不更改寄存器。未设置零鞭毛(请参见 JNZ )如果结果不为null->奇数。

    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
    
        3
  •  0
  •   Ahtisham    7 年前

    我考虑过只选一个,根据比较 创建和或差。

    这就是只使用一个循环(根据索引值求和或求差)的方法:

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

      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寄存器的值进行求和或求差(可以是偶数或奇数)