这段代码中 ADD BX,2 的目的是什么?
What is the purpose of ADD BX,2 in this code?
我试图理解这个递归代码,但我对 add bx, 2
的目的是什么感到困惑。我已经在相关行上做了标记。据我了解,我们必须使用值来增加指向数组的指针,但为什么我们要添加 2 而不是 1?
.model small
.stack 100
.data
arr dw 38, 39, 90, 94, 13, 24, 53, 59, 63
size dw 9
result dw ?
.code
func proc
push bp
mov bp, sp
push ax
push bx
push cx
push dx
mov cx, [bp+4]
mov bx, [bp+6]
mov ax, [bx]
cmp cx, 1
ja more
mov [bp+6], ax
jmp done
more:
**add bx, 2**
push bx
dec cx
push cx
call func
pop dx
cmp dx, ax
jg greater
mov [bp+6], ax
jmp done
greater:
mov [bp+6], dx
done:
pop dx
pop cx
pop bx
pop ax
pop bp
ret 2
func endp
As i understand we have to increment the pointer pointing at the array with the values but why we are adding 2 and not 1?
如果我没理解错的话,BX
指向包含 16 位值的数组中元素的地址。
指令 mov ax, [bx]
向您展示了元素是 16 位值,而不是 8 位或 32 位值。 16 位值的长度为 2 个字节。
在大多数 CPU 上(有 TMS 320 或 TMS 9900 等例外)如果元素的长度为 n
字节,则数组中两个元素的地址之间的差异为 n
。
所以如果x
是包含16位值的数组中元素的地址,y
是下一个元素的地址,那么y-x=2
.
因此必须在 BX
中加上两个才能得到下一个元素的地址。
注意后面的 push bx
/ ... / call func
:这是一个递归函数,它会将 bx+2
传递给下一个调用。
我认为 BX 被用作指针,并且有一个 arr
,它是一个 "words"(2 个字节)的数组,所以这几乎可以肯定是一个指针增量。
这看起来非常效率低下;它只是单递归的,所以它可以很容易地写成一个循环。 例如do { something with *p++; } while(--cx);
在 C 中,即底部有 dec cx / jnz
的循环。
分支也很愚蠢:它可以在保存尽可能多的寄存器之前更早地检查递归终止条件。它可以通过使用 jna done
使 jmp
脱离函数的正常路径。也许它需要跳转到函数末尾的一个特殊块,在特殊情况路径上进行 2 次跳转,但这仍然比在主路径上进行 2 次跳转要好。
storing/reloading [bp+6]
的东西也很奇怪。此函数 return 是否通过修改其在堆栈上的参数之一来实现?它看起来是基于 pop dx
通话后的样子。我希望这是有意混淆的,或者写成优化的起点,因为这看起来非常复杂。
根据分支目标名称,我假设它只是在给定指针和长度的情况下找到数组中的最大有符号字。这是微不足道的,而且循环效率更高。
我试图理解这个递归代码,但我对 add bx, 2
的目的是什么感到困惑。我已经在相关行上做了标记。据我了解,我们必须使用值来增加指向数组的指针,但为什么我们要添加 2 而不是 1?
.model small
.stack 100
.data
arr dw 38, 39, 90, 94, 13, 24, 53, 59, 63
size dw 9
result dw ?
.code
func proc
push bp
mov bp, sp
push ax
push bx
push cx
push dx
mov cx, [bp+4]
mov bx, [bp+6]
mov ax, [bx]
cmp cx, 1
ja more
mov [bp+6], ax
jmp done
more:
**add bx, 2**
push bx
dec cx
push cx
call func
pop dx
cmp dx, ax
jg greater
mov [bp+6], ax
jmp done
greater:
mov [bp+6], dx
done:
pop dx
pop cx
pop bx
pop ax
pop bp
ret 2
func endp
As i understand we have to increment the pointer pointing at the array with the values but why we are adding 2 and not 1?
如果我没理解错的话,BX
指向包含 16 位值的数组中元素的地址。
指令 mov ax, [bx]
向您展示了元素是 16 位值,而不是 8 位或 32 位值。 16 位值的长度为 2 个字节。
在大多数 CPU 上(有 TMS 320 或 TMS 9900 等例外)如果元素的长度为 n
字节,则数组中两个元素的地址之间的差异为 n
。
所以如果x
是包含16位值的数组中元素的地址,y
是下一个元素的地址,那么y-x=2
.
因此必须在 BX
中加上两个才能得到下一个元素的地址。
注意后面的 push bx
/ ... / call func
:这是一个递归函数,它会将 bx+2
传递给下一个调用。
我认为 BX 被用作指针,并且有一个 arr
,它是一个 "words"(2 个字节)的数组,所以这几乎可以肯定是一个指针增量。
这看起来非常效率低下;它只是单递归的,所以它可以很容易地写成一个循环。 例如do { something with *p++; } while(--cx);
在 C 中,即底部有 dec cx / jnz
的循环。
分支也很愚蠢:它可以在保存尽可能多的寄存器之前更早地检查递归终止条件。它可以通过使用 jna done
使 jmp
脱离函数的正常路径。也许它需要跳转到函数末尾的一个特殊块,在特殊情况路径上进行 2 次跳转,但这仍然比在主路径上进行 2 次跳转要好。
storing/reloading [bp+6]
的东西也很奇怪。此函数 return 是否通过修改其在堆栈上的参数之一来实现?它看起来是基于 pop dx
通话后的样子。我希望这是有意混淆的,或者写成优化的起点,因为这看起来非常复杂。
根据分支目标名称,我假设它只是在给定指针和长度的情况下找到数组中的最大有符号字。这是微不足道的,而且循环效率更高。