Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 在汇编语言中执行操作时,为什么必须在字符串中添加-2? 添加-2的第一个实例(添加cx,-2)_Assembly_Dos_X86 16 - Fatal编程技术网

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
    指令放在
    [si]
    读取之前(我们称之为预减量),可以在循环从L1开始之前删除一条指令
  • 我用
    mov
    替换了所有
    lea
    。结果是相同的,但代码缩短了1字节。每一次
  • 我已将慢速
    循环
    指令替换为等效的code
    dec-cx
    jnzl1
  • 我已经用一条等价的指令替换了这对指令
    mov[di],al
    inc di
    。我之所以可以这样做,是因为
    ES
    寄存器已经设置好,并且我已经清除了方向标志(DF)。您的
    重复cmpsb
    也取决于DF=0
  • 我用一条指令
    mov byte ptr[di],“$”
    替换了一对写入新$terminator的指令

您需要指向字符串中最后一个字符的指针。通常情况下,由于基于零的索引,这当然是
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], '$'