将 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 位模式下)?的主要内容,如果未能解决你的问题,请参考以下文章

第七章 更灵活的定位内存地址的方法 知识梳理

IP寻址方式三

汇编语言基础总结

freescale 16位单片机的地址映射

通用寄存器都有哪些?

第二章总结