Assembly 在汇编语言中执行操作时,为什么必须在字符串中添加-2? 添加-2的第一个实例(添加cx,-2)
考虑 在这里,为什么更喜欢Assembly 在汇编语言中执行操作时,为什么必须在字符串中添加-2? 添加-2的第一个实例(添加cx,-2),assembly,dos,x86-16,Assembly,Dos,X86 16,考虑 在这里,为什么更喜欢添加si,-2而不是可读性更高的子si,2? 由于strlen1是如何定义的(strlen1 dw$-str1),因此add si,strlen1将使si点位于终止的$字符后面。 减去1将使SI指向终止的$字符,因此位于字符串的最后一个字符之后。 减去2将使SI指向at字符串的最后一个字符 暗示 如果重新定义strlen1,使其不包含终止的$character,则上述许多问题将不存在。当人们谈论字符串的长度时,他们很少在计数中包含任何终止字符。这样的字符(无论是$还是
添加si,-2
而不是可读性更高的子si,2
?由于strlen1是如何定义的(
strlen1 dw$-str1
),因此add si,strlen1
将使si
点位于终止的$字符后面。减去1将使
SI
指向终止的$字符,因此位于字符串的最后一个字符之后。减去2将使
SI
指向at字符串的最后一个字符
暗示 如果重新定义strlen1,使其不包含终止的$character,则上述许多问题将不存在。当人们谈论字符串的长度时,他们很少在计数中包含任何终止字符。这样的字符(无论是$还是零)实际上不是字符串的一部分
lea si, str1
add si, strlen1
add si, -2
要在上下文中查看所有内容:
strlen1 dw $ - str1 - 1 ;Length of the string
请注意以下细节:
- 我已将显示在屏幕上的代码与执行反转的代码完全分离
- 通过将
指令放在dec si
读取之前(我们称之为预减量),可以在循环从L1开始之前删除一条指令[si]
- 我用
替换了所有mov
。结果是相同的,但代码缩短了1字节。每一次lea
- 我已将慢速
指令替换为等效的code循环
dec-cx
jnzl1
- 我已经用一条等价的指令替换了这对指令
mov[di],al
。我之所以可以这样做,是因为inc di
寄存器已经设置好,并且我已经清除了方向标志(DF)。您的ES
也取决于DF=0重复cmpsb
- 我用一条指令
替换了一对写入新$terminator的指令mov byte ptr[di],“$”
start+length-1
。它变成了-2
,因为最后有一个$
你不想处理。你实际上不需要在运行时添加,那只是写得不好的代码。你可以做movcx,strlen1-2
。(哦,nvm,strlen1
是存储在内存中的一个值,而不是eq
常量,所以你不能这样做。这也很愚蠢。)使用mov si,OFFSET str1
也总是比使用lea si,str1
更好,因为它比较小,可以在更多的执行端口上运行。如果你只想检查回文的话,那么做一个字符串的反向拷贝也是没有意义的:最好在两端用指向中间的指针开始。
L1:
mov al, [si]
mov [di], al
dec si
inc di
loop L1
mov al, [si] <-- Should stay inside the loop
mov [di], al <-- Should stay inside the loop
inc di <-- Should stay inside the loop
lea si, str1
add si, strlen1
add si, -2
strlen1 dw $ - str1 - 1 ;Length of the string
mov ah, 09h
mov dx, s1
int 21h
mov ah, 09h
mov dx, str1
int 21h
mov ah, 09h
mov dx, NEWLINE
int 21h
cld ;To be absolutely safe
mov cx, strlen1 ;The improved definition! db 'MADAME','$' => 5
mov di, strrev
mov si, str1
add si, cx ;Now points behind the last character ('E')
L1:
dec si
mov al, [si]
stosb ;Equivalent to "mov [di], al" "inc di"
dec cx
jnz L1
mov byte ptr [di], '$'