为何1字节变量boxresult能存储"yes"/"no"?NASM汇编疑问
你遇到的现象是未定义行为,并非boxresult resb 1d真的能存储多字符,问题出在代码里的错误内存操作:
核心错误分析
错误的寄存器读取
你用mov eax, [yes]时,eax是32位寄存器,会从yes地址开始读取4字节数据。yes是db "yes", 0h定义的,实际占4字节('y'、'e'、's'、0),这条指令会把这4字节全部读到eax里;同理mov eax, [no]会读取no地址开始的4字节('n'、'o'、0,再加上no后面内存的1个随机字节)。越界内存写入
mov [boxresult], eax是将eax里的4字节写入boxresult,但你只给boxresult预留了1字节空间。这会直接覆盖boxresult后面的3字节内存——也就是.bss段里written变量的空间(因为.bss里变量是按定义顺序排列的)。这种越界写入属于非法操作,只是因为程序逻辑简单,没有立刻触发崩溃,才让你误以为“存储成功”。巧合的输出结果
你调用_WriteFile@20时指定了输出3字节,读取的是boxresult开始的3字节。由于之前越界写入的4字节里,前3字节正好是"yes"或"no",所以输出看起来正确,但这完全是巧合,换个编译环境或修改变量顺序,程序大概率会出错。
关于resb的正确认知
resb 1d确实只会在.bss段预留1字节的未初始化空间,并不具备存储多字符的能力。你看到的“正常运行”是错误操作导致的偶然结果,不属于合法用法。
修正方案
方案1:正确预留足够空间
把.bss里的boxresult resb 1d改成boxresult resb 4d(预留4字节,足够容纳"yes\0"或"no\0"),避免越界写入。
方案2:直接使用字符串地址(更高效)
如果只是要输出选择结果,完全不需要把字符串复制到boxresult,可以直接把yes或no的地址传给WriteFile,修改代码如下:
cmp eax, IDYES jne else push yes ; 直接传yes的地址 jmp write else: push no ; 直接传no的地址 write: push 0h push 0h push 3d ; 这里替换原来的push boxresult,直接用上面push的地址 push dword [StandardOutputHandler] call _WriteFile@20
内容的提问来源于stack exchange,提问作者Gufler

