首页 > 解决方案 > 汇编中字符串的长度(对程序如何工作的困惑)

问题描述

我有一个汇编程序,它在 ax 寄存器中写入字符串的长度,但我对一些指令有点困惑。

include \masm32\include64\masm64rt.inc
.data
string db "mama", 0        ; so here I declared a string "mama". What happens in memory?
.code
 main proc
xor ax, ax                 ; here I initialize ax with 0.
lea rsi, string            ; here, I move in rsi register the adress of string, right? But how the string is stored in memory? Now in rsi I have the adress of the first char "m" of "mama" string?
 @@:                       ; this sign creates an anonymous label
cmp byte ptr [rsi], 0      ; so this says compare 0 with with 1 byte found at the adress pointed to by rsi, right? But I still don't get it. Why 1 byte? rsi is pointing to the first char or to the whole string?
jz @F                      ; jump if zero to the nearest @@ (forward)
inc ax                     ; so now i'm pointing to the first character so ax=1
inc rsi                    ; here what happen? The pointer is incremented to point to the second char from string?
jmp @B                     ; jump to the nearest @@ (backward)
 @@:
invoke ExitProcess, 0 ; invoke ExitProcess API
ret
 main endp
end

我的困惑是我不确定我是否考虑过这个程序是如何以正确的方式工作的。我这样想对吗?

标签: stringassemblymasm

解决方案


string db "mama", 0

4 个字节0x6d 0x61 0x6d 0x61('mama')存储在程序内存的数据段中的某处。string将第一个字节的地址存储在数据段中,即“m”。

xor ax, ax

lea rsi, string

相信手术应该是lea rsi, [string]。(编辑:正如Peter Cordes在下面的评论中提到的,在 MASM 汇编器中,这种语法很好)

string指向第一个字符的地址。现在rsi指向同一个地址。

@@:                       ; this sign creates an anonymous label

cmp byte ptr [rsi], 0

rsi 指向整个字符串的开头。比较操作将 rsi 处的一个字节与零进行比较。如果为零,则假定字符串结束并跳转到退出:

jz @F                      ; jump if zero to the nearest @@ (forward)

如果 rsi 的值不为零:

inc ax

请记住,我们将字符串的长度存储在 ax 中。因此,对于每个有效字符,我们递增ax1。

inc rsi

jmp @B                     ; jump to the nearest @@ (backward)

指向rsi下一个字符 ('a') 并跳转到 @@。第一个 @@ 之后的代码将再次检查下一个字符 ('a') 是否为零,并将计数 ( ax) 增加 1,因此ax将变为 2。这将一直持续到达到 0,程序假定结束的字符串。

@@:

invoke ExitProcess, 0 ; invoke ExitProcess API

ret

 main endp

end

退出代码。

旁注:您可以使用像 gdb 这样的程序,在开始时带有断点来遍历每个步骤。使用info registers命令,您可以检查它们的值。向谷歌询问更高级的命令/方法。


推荐阅读