由两个字符串的 summing/subtracting 个字符创建一个新数组
Creating a new array by summing/subtracting characters of two strings
从 2 个字节数组 S1 和 S2 开始,应该根据以下规则创建第三个数组:在偶数位置应该是 S1 和 S2 中特定字符的总和,在奇数位置位置应该是 S1 和 S2 中特定字符的差异
示例:
;S1: 1, 2, 3, 4
;S2: 5, 6, 7, 8
;D: 6, -4, 10, -4
我试过根据 2 "for loops" 按以下方式实现它,但在尝试了几次之后,我发现它可能永远不会工作,因为它们不是同时的。我考虑过只使用一个并基于比较来创建总和或差异。问题是,我不太确定这种比较应该如何进行(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
提前致谢,对任何mistakes/inconveniences感到抱歉。
正如@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
)。梯子是你作业的主要部分,因为处理负号和多于一位的数字有点挑战。
SI、DI 和 BX 必须在您的 2 循环解决方案中增加 2。 LODSB
和 STOSB
仅递增 1。因此您为该寄存器添加了额外的递增。你忘了增加 BX。
这里没关系,但是... JL
和 JLE
执行 signed 比较。 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 指令,它执行 AND
但仅设置标志而不更改寄存器。如果结果不为空 -> 奇数,则不设置零标志(参见 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
I've considered going just with one and based on a comparison, to
create the sum or the difference.
这就是你如何只用一个循环(你根据索引值求和或求差):
只需用以下代码替换您的两个循环:-
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 寄存器的值(可以是偶数或奇数)求和或求差
从 2 个字节数组 S1 和 S2 开始,应该根据以下规则创建第三个数组:在偶数位置应该是 S1 和 S2 中特定字符的总和,在奇数位置位置应该是 S1 和 S2 中特定字符的差异
示例:
;S1: 1, 2, 3, 4
;S2: 5, 6, 7, 8
;D: 6, -4, 10, -4
我试过根据 2 "for loops" 按以下方式实现它,但在尝试了几次之后,我发现它可能永远不会工作,因为它们不是同时的。我考虑过只使用一个并基于比较来创建总和或差异。问题是,我不太确定这种比较应该如何进行(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
提前致谢,对任何mistakes/inconveniences感到抱歉。
正如@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
)。梯子是你作业的主要部分,因为处理负号和多于一位的数字有点挑战。SI、DI 和 BX 必须在您的 2 循环解决方案中增加 2。
LODSB
和STOSB
仅递增 1。因此您为该寄存器添加了额外的递增。你忘了增加 BX。这里没关系,但是...
JL
和JLE
执行 signed 比较。 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。您可以 AND
带 1 的数字并得到 0(未设置)或 1(已设置)。 TEST
是一种特殊的 x86 指令,它执行 AND
但仅设置标志而不更改寄存器。如果结果不为空 -> 奇数,则不设置零标志(参见 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
I've considered going just with one and based on a comparison, to create the sum or the difference.
这就是你如何只用一个循环(你根据索引值求和或求差):
只需用以下代码替换您的两个循环:-
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 寄存器的值(可以是偶数或奇数)求和或求差