将 foo[si] 之类的 16 位地址与 Irvine32 一起使用(在 32 位模式下)?
Posted
技术标签:
【中文标题】将 foo[si] 之类的 16 位地址与 Irvine32 一起使用(在 32 位模式下)?【英文标题】:Using 16-bit addresses like foo[si] with Irvine32 (in 32-bit mode)? 【发布时间】:2021-11-29 03:36:49 【问题描述】:由于某种原因,当我在调试时它停在mov al,data1[si]
并给了我一个异常
第 5 周.exe 在 0x00D53668 处引发异常:0xC0000005:访问冲突读取位置 0x01AA6000。
我可以知道是什么原因吗?
INCLUDE Irvine32.inc
.data
data1 byte "MILK",0
data2 byte 4 dup('*'),0
.code
main proc
mov CX,4
mov si,0
l1:
mov al,data1[si] <<EXCEPTION THROWN AT THIS LINE>>
mov data2[si],al
inc si ; before go in the loop l1, cx will auto deduct by 1, then cx==0?
loop l1
mov EDX, offset data2
call WriteString
exit
main endp
end main
【问题讨论】:
0x01AA6000
是您要读取的正确地址吗?
【参考方案1】:
您已标记您的问题x86 和irvine32,这表明您正在使用 32 位指令,但正在尝试使用 16 位索引寄存器(=SI
)
mov al,data1[si]
这(几乎)肯定会失败。改用(并在之前设置)像 ESI
这样的 32 位寄存器:
mov al, byte ptr data1[esi]
如果您正在编写 32 位代码,您通常应该将 32 位寄存器用于您的正常程序流程。而 16 位的只有在罕见的、经过深思熟虑的场合。
【讨论】:
嗨,谢谢zx485,但是如果我坚持用户[si],我应该配置什么才能执行它。我正在使用视觉工作室! @JoshuaTabi:Windows 可能不允许您在低 64kiB 的虚拟地址空间中使用 VirtualAlloc 内存(这是您使用 16 位地址所能达到的全部)。将链接器配置为将.data
、.bss
和.rdata
部分映射到如此低的地址而不是它们的默认位置可能也很不方便。 (在 Linux 上,请参阅 mmap_min_addr
设置,您可以使用链接描述文件。)
@JoshuaTabi:但总体而言,尝试在 32 位代码中使用 16 位地址非常不方便,而且性能更差。所以你评论的答案只是作为一个愚蠢的计算机技巧/假设,而不是你真正想做的事情。
在 32 位模式下不能有 16 位索引寄存器,因为它没有指令编码。请查看 Intel 说明手册 中的表 2.2 和 2.3(32 位寻址形式)以确认这一点。
澄清一下,您不能在像mov al,data1[si]
这样的索引表达式中使用SI
。但当然,您可以在其他指令(生成 16 位前缀)中使用它,例如 inc si
。而且,一般来说,这仅在特殊情况下有用。以上是关于将 foo[si] 之类的 16 位地址与 Irvine32 一起使用(在 32 位模式下)?的主要内容,如果未能解决你的问题,请参考以下文章