HLA中获取输入字符串长度遇异常,求代码修正方案
HLA字符串长度计算问题修正
先看你代码里的几个核心问题:
- strlen函数栈处理完全错误:用
@noframe时,栈顶是返回地址,下面跟着参数。你原代码里pop(return)后直接pop(EBX),这把参数存到EBX,但后面又把保存的iEBX压栈,完全打乱了栈结构,导致参数读取错误。 - 循环逻辑根本没循环:你的
WhileInc里执行一次inc(ECX)和inc(EDX)就跳去EndSequence,等于只检查第一个字符就结束,根本没遍历到字符串末尾的空字符。 - 输出对象错了:你最后输出的是
AL,而AL存的是字符串首字符的ASCII值,自然会输出首字符的十进制数,应该输出计数用的EDX。 - 主程序里多余的动态内存操作:
strData是静态定义的32字节数组,不需要用malloc分配内存,这段代码完全没用,还容易出问题。
下面是修正后的完整代码:
program strlenFunction; #include( "stdlib.hhf" ); #include( "cs17string.hla" ); static strData : byte[32]; strLength : uns16 := 31; // 最大输入字符数(留1位存空字符) procedure strlen( baseStringAddress: dword ); @nodisplay; @noframe; static returnAddr: dword; savedEBX: dword; savedECX: dword; savedEDX: dword; begin strlen; // 保存需要用到的寄存器(调用者保存寄存器) mov(EBX, savedEBX); mov(ECX, savedECX); mov(EDX, savedEDX); // 手动处理栈:弹出返回地址和参数 pop(returnAddr); pop(EBX); // EBX现在存字符串基地址 push(returnAddr); // 把返回地址压回去 mov(0, EDX); // 初始化长度计数器为0 mov(EBX, ECX); // ECX指向当前字符位置 countLoop: mov([ECX], AL); cmp(AL, 0); // 检查是否是空字符 je endCount; // 是空字符就退出循环 inc(EDX); // 计数器+1 inc(ECX); // 指向下一个字符 jmp countLoop; // 回到循环开头 endCount: stdout.puti32(EDX); // 输出计算好的长度 // 恢复寄存器 mov(savedEBX, EBX); mov(savedECX, ECX); mov(savedEDX, EDX); ret(); end strlen; begin strlenFunction; stdout.put("Feed Me: "); mov(&strData, EAX); push(EAX); push(strLength); call gets; stdout.put("The String You Entered: "); mov(&strData, EAX); push(EAX); call puts; stdout.put(" Has Length = "); mov(&strData, EAX); push(EAX); call strlen; stdout.newln(); // 换行,让输出更规范 end strlenFunction;
关键修改说明:
- 栈处理修正:先保存寄存器,再弹出返回地址和参数,处理完后把返回地址压回栈,保证函数返回时能正确跳转。
- 循环逻辑修正:改成真正的循环,每次检查当前字符是否为空,非空就递增计数器和指针,直到遇到空字符才退出。
- 输出修正:输出
EDX里的计数器值,而非首字符的AL。 - 删除冗余代码:去掉了没用的
iSize、dArrayBaseAddress以及malloc/free相关代码,简化程序。
测试输入asdf的话,会输出你期望的结果:
Feed Me: asdf The String You Entered: asdf Has Length = 4
内容的提问来源于stack exchange,提问作者Jes
相关产品推荐
相关产品推荐

