给定变量:
var1 db "abcdefg", NULL
如何执行循环以遍历每个字母?在C++中,您可以在循环内使用var[x],然后每次增加x。有什么想法吗?
strlen
从字符串的开头开始遍历,并持续循环,直到它遇到这个 NUL 字符为止。当它找到 NUL 时,它就知道这是字符串的结尾,并返回从开头到 NUL 的字符数作为该字符串的长度。"abcdefg"
等同于以下数组:
{'a', 'b', 'c', 'd', 'e', 'f', 'g', 0}
var1 db "abcdefg", NULL
通常情况下,我们不使用标识符NULL
来表示这个意思。特别是在C语言中,NULL
被定义为一个空指针。我们只需使用字面值0,因此该定义将是:
var1 db "abcdefg", 0
假设NULL
在某处被定义为0,那么你的代码可能会正常工作。
所以你已经全部设置正确。现在你只需要编写循环:
mov edx, OFFSET var1 ; get starting address of string
Loop:
mov al, BYTE PTR [edx] ; get next character
inc edx ; increment pointer
test al, al ; test value in AL and set flags
jz Finished ; AL == 0, so exit the loop
; Otherwise, AL != 0, so we fell through.
; Here, you can do do something with the character in AL.
; ...
jmp Loop ; keep looping
Finished:
你说你熟悉 CMP
指令。在上面的代码中,我使用了 TEST
而不是 CMP
。你可以等价地编写:
cmp al, 0
但是
test al, al
使用这种写法略微更高效,因为它是一条较短的指令,所以当我比较寄存器的值是否为0时,我习惯于以这种方式编写。编译器也会生成这段代码,所以熟悉这种写法很有好处。
额外讲述: 一种表示字符串的替代方式是将字符串的长度(以字符为单位)与字符串本身一起存储。这是传统Pascal语言所做的。这样,您就不需要在字符串末尾使用特殊的NUL哨兵字符。相反,声明将如下所示:
var1 db 7, "abcdefg"
mov edx, OFFSET var1 ; get starting address of string
mov cl, BYTE PTR [edx] ; get length of string
Loop:
inc edx ; increment pointer
dec cl ; decrement length
mov al, BYTE PTR [edx] ; get next character
jz Finished ; CL == 0, so exit the loop
; Do something with the character in AL.
; ...
jmp Loop ; keep looping
Finished:
mov edx, OFFSET var1 ; get starting address of string
movzx ecx, BYTE PTR [edx] ; get length of string
lea edx, [ecx+1] ; increment pointer by 1 + number of chars
neg ecx ; negate the length counter
Loop:
mov al, BYTE PTR [edx+ecx] ; get next character
; Do something with the character in AL.
; ...
inc ecx
jnz Loop ; CL != 0, so keep looping
EDX
设置为指向字符串的末尾,将计数器(ECX
)设置为字符串长度的负数,然后通过索引[EDX+ECX]
(由于我们取反了ECX
,所以等同于[EDX-ECX]
)来读取字符。
肯定有比我想出的更好(更聪明)的方法来做到这一点,但你应该明白了。
mov al,[var1 + edx]
的简单解决方案应该是合适的。 - Ajay Brahmakshatriyamov al, BYTE PTR [var1 + index]
(其中index是立即值或包含该值的寄存器)就可以工作。不确定我是否应该让答案更长。 :-) - Cody Grayrep scasb
可以用于通过搜索终止的 NUL 字符来查找字符串的长度。这是一种在汇编语言中实现strlen
的(极其)低效的方法(除非你是为 8088 编程)。 - Cody Gray