通过对两个字符串的字符求和/减去来创建一个新数组
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
代码存在一些问题。
- 您无法添加或减去字符。字符不会存储为数字,而是存储为ASCII码。您可以将ASCII代码想象为监视器的命令以显示特定字符。处理器需要另一种格式来将其作为整数处理。你必须转换它(如果你想显示它,则返回)。角色的ASCII部分是高半字节。要获得整数删除它(
AND 0Fh
或SUB 48
)。要获取字符,请将ASCII部分添加到整数(OR 30h
或ADD 48
)。梯子是你的家庭作业的主要部分,因为处理负号和数字超过一位数有点挑战。 - 使用2循环解决方案,SI,DI和BX必须增加2。
LODSB
和STOSB
只增加1.因此,您为该寄存器添加了额外的增量。你忘了增加BX。 - 这没关系,但是......
JL
和JLE
进行了签名比较。 CX不太可能变为负面。所以把它改成未签名的camparisonsJB
和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。你可以用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寄存器的值(可以是偶数或奇数)进行求和或差值
以上是关于通过对两个字符串的字符求和/减去来创建一个新数组的主要内容,如果未能解决你的问题,请参考以下文章