IA32汇编STOS*指令未将值存入inArray的问题求助
IA32汇编STOS*指令未正确写入目标数组问题
需求背景
我是在校学生,正在编写IA32汇编程序,需求如下:
- 读取用户输入的最大32位数字字符串
- 使用LODS*指令逐个提取字符,转换为十进制数值后存入
inArray数组 - 后续将数组中的十进制值转回ASCII格式输出
当前问题
LODS指令的字符提取和数值转换流程看似正常,但STOS指令并未将转换后的值写入inArray,而是写入了程序的十六进制代码内存区域。测试输入字符串'1234',期望十进制值1234存入inArray,实际却存储到了程序代码段的内存中。此前请教教授和助教未能解决,特此求助。
相关代码片段
; main函数示例(根据实际代码调整) section .text global main main: ; 初始化栈帧 push ebp mov ebp, esp ; 调用ReadVal过程处理输入 call ReadVal ; 后续输出逻辑... mov esp, ebp pop ebp ret ; ReadVal过程:读取输入字符串并转换为十进制值存入inArray ReadVal: push ebp mov ebp, esp ; 初始化SI指向输入缓冲区 mov esi, inputBuf ; 初始化DI指向inArray(此处可能存在问题) mov edi, inArray convert_loop: ; LODSB读取单个ASCII字符 lodsb ; 判断是否到字符串结束符 cmp al, 0 je convert_done ; ASCII转十进制数字(减去'0'的ASCII码48) sub al, 48 ; 累加生成完整数值(示例逻辑,需根据实际代码调整) mov bl, al mov eax, [edi] mov ecx, 10 mul ecx add eax, ebx ; STOSD将结果存入inArray(假设数组元素为双字) stosd jmp convert_loop convert_done: mov esp, ebp pop ebp ret section .data inputBuf db '1234', 0 inArray dd 0 ; 存储转换后的十进制值
问题本质分析方向
STOS*指令默认以ES:DI作为目标地址,写入错误区域通常和段寄存器配置或目标地址初始化错误直接相关,核心可能原因包括:
- ES段寄存器未映射到数据段:IA32中STOS*依赖ES段,如果ES未与DS(数据段)设置为相同的段基址/选择子,即使DI指向
inArray的偏移,实际访问的是ES对应的内存区域(比如代码段)。实模式下需确保ES = DS,保护模式下要确认ES的段选择子正确映射数据段。 - DI寄存器初始化或被篡改:检查
inArray的偏移是否正确加载到DI,是否在过程执行中被其他操作意外修改(比如调用未保护寄存器的子过程),导致STOS*时DI指向了代码段内存。 - 数组的段定义错误:如果
inArray误定义在代码段(.text)而非数据段(.data),即使地址计算正确,写入的也是程序代码内存区。 - 操作数大小不匹配:如果
inArray是双字(32位)数组,但使用了STOSB(字节操作),或反之,会导致内存寻址计算错误,间接引发写入位置偏差。
调试建议
- 用调试器(GDB/OllyDbg)在
ReadVal过程的STOS*指令处设断点,查看执行前ES和DI的值,对比inArray的实际内存地址(数据段基址+偏移),确认ES:DI是否指向inArray的正确位置。 - 检查寄存器保护逻辑:如果
ReadVal中修改了DI、ES等寄存器,需确保用push/pop保存和恢复,避免破坏调用者的寄存器状态。 - 验证段定义:查看汇编器输出的目标文件,确认
inArray所在段的属性为数据段(可写),而非代码段(只读/执行)。 - 单步执行LODS和STOS指令,观察每一步的内存变化,确认转换后的数值是否正确,以及写入的内存地址是否符合预期。
内容的提问来源于stack exchange,提问作者Smiththedude
相关产品推荐
相关产品推荐

