String 在程序集中的字符串上迭代(NASM)
我试图用NASM汇编语言计算字符串argv[1]的长度。我想我走对了。我已经将argv[1]的地址移到了寄存器eax,现在我想逐字节地遍历它,并与空字符串终止符进行比较 每次我运行代码时,它都会在空比较中出错。我的内存索引是否正确 *免责声明:这是大作业的一小部分String 在程序集中的字符串上迭代(NASM),string,memory,assembly,nasm,memory-address,String,Memory,Assembly,Nasm,Memory Address,我试图用NASM汇编语言计算字符串argv[1]的长度。我想我走对了。我已经将argv[1]的地址移到了寄存器eax,现在我想逐字节地遍历它,并与空字符串终止符进行比较 每次我运行代码时,它都会在空比较中出错。我的内存索引是否正确 *免责声明:这是大作业的一小部分 segment .bss N: resd 1 ;counter for size of argv[1] segment .text global asm_main asm_main: en
segment .bss
N: resd 1 ;counter for size of argv[1]
segment .text
global asm_main
asm_main:
enter 0,0 ;setup
pusha ;save all registers
mov eax, dword [ebp+8] ;argc to eax
mov ebx, dword [ebp+12] ; address of argv to ebx
mov eax, dword [ebx+4] ; address of argv[1] to eax
mov [N], dword 0 ; N = 0
.loop:
add eax, [N] ; advance index by N
cmp eax, dword 0 ; check for end of string
je .endloop ; break out of the loop if we're done
add [N], dword 1 ; N++
jmp .loop ; loop back for next char
.endloop:
popa
mov eax, 0
leave
ret
在一些提示和gdb的帮助下,循环现在看起来如下所示:
mov [N], dword 0 ; N = 0
.loop:
cmp [eax], byte 0 ; check for end of string
je .endloop
add eax, dword 1 ; advance index by 1 byte
add [N], dword 1 ; N++
jmp .loop
.endloop:
使用N来增加索引是愚蠢的。我需要增加1。它实际上是在哪个指令上启动的
addeax,[N]
从固定地址读取数据,因此如果它第一次没有SEGFULT,它就永远不会SEGFULT。使用调试器进行单步调试,查看出现故障时regs/mem中的内容。这里最明显的问题是,您从不读取字符串,只需增加一个指针并将其与零进行比较。(并且您以几何方式递增eax,因为[N]
线性递增。)它在cmp线上消亡。你是对的,我上面的这行比较了地址(希望是字符的地址)和期望值,而不是字符本身。我应该有cmp[eax],dword 0吗?字符串应该是[byte][byte][byte]…[null]。所以不是dword,而是字节。EAX应该将地址保存到字节。[EAX]应该是有问题的字节。cmp[eax],字节0?@PeterCordes当我在调试器上看到它时,我只是/面对它。请注意,您不需要单独的计数器。您只需执行子eax,在循环后启动\u字符串的\u即可。(如果可以避免,请不要将循环计数器保留在内存中。它非常慢。在大多数英特尔CPU上,代码的运行速度几乎是在寄存器中保留N(或完全避免)时的6倍),因为它将存储/重新加载往返放入循环携带的依赖链中,并且在Intel SnB系列CPU上存储转发延迟为5个周期。)。虽然我很感激您知道所使用数据的大小,但JFYI:theadd eax,dword 1
不需要大小说明符,因为一侧的eax
强制执行指令的32b大小的上下文。因此,在这种情况下,添加eax,1就足够了。下面的一个是正确的,dword 1至少在一侧需要大小说明符,因为没有它是不明确的,如果N
只是字节/字,那么byte
或word
也有意义。要执行+-1操作,x86具有专用的操作码inc
和dec
,保存了该,1
的键入。不知道为什么我真的喜欢这两个