【问题标题】:Access violation writing location in assembly x86汇编x86中的访问冲突写入位置
【发布时间】:2013-05-06 05:33:41
【问题描述】:

您好,我有一个关于汇编 x86 的问题

这是我的代码

INCLUDE Irvine32.inc
.data
day WORD 0
month WORD 0
year WORD 0


prompt1 BYTE "enter month: ",0
prompt2 BYTE "enter day: ",0
prompt3 BYTE "enter an year: ",0
prompt4 BYTE " the day of the week is ",0

.code
main PROC

mov edx, OFFSET prompt1
call writeString
mov edx, 0
call readInt
call crlf
mov month, ax

mov eax, 0
mov edx, OFFSET prompt2
call writeString
mov edx, 0
call readInt
call crlf
mov day, ax


mov eax, 0
mov edx, OFFSET prompt3
call writeString
mov edx, 0
call readInt
call crlf
mov year, ax



mov eax, 0
mov ebx, 0
mov ax, 14
sub ax, month
mov bx, 12
div bx
mov si, ax ;; a store in si
sub year, ax
mov di, year ;; y store in di
mov ax, ax
mul bx
add ax, month
mov cx, 2
sub ax, cx
mov ecx, 0
mov cx, ax ;; m store in cx

mov eax, 0
mov ebx, 0
mov esp, 0
mov ebp, 0

add day, di
mov ax, di
mov bx, 4
div bx
add day, ax
mov sp, day
mov eax, 0
mov ebx, 0
mov ax, di
mov bl, 100
div bl
mov ah, 0
sub day, ax


mov eax, 0
mov ebx, 0
mov dx, 0
mov ax, di
mov bx, 400
div bx
add day, ax
mov bp, day  ;; temporary holder for d value up to y/400 calculation

mov eax, 0
mov ebx, 0
mov ax, 31
mul cx
mov bx, 12
div bx
add bp, ax
mov al, 7
div al




    exit
main ENDP

END main

我正在调试这段代码,一切似乎都相应地工作,直到我到达退出指令,然后 Visual Studio 给了我这个错误“访问冲突写入位置 0x000009DF”,我有点困惑,它在结束时给了我这个错误代码,为什么exit命令会出现访问冲突

这是我的输入

enter month: 4

enter day: 15

enter an year: 2013

在程序结束时,我得到寄存器 al = 1 的值,这就是我想要的 所以我不知道为什么当代码中没有其他错误时它给了我这个错误 谁能帮忙? 提前感谢

【问题讨论】:

    标签: assembly x86 masm access-violation irvine32


    【解决方案1】:

    要访问内存位置,请使用括号,因为它更容易阅读。

     mov [year], ax
    
     mov di, [year]
    

    最好防止对代码的误解,因为如果我们使用

    mov di, year
    

    它可能会被误认为

    mov di, offset year
    

    因为如果我们使用 NASM 而不是 MASM,那么这条指令不需要偏移量声明来获取偏移地址。 NASM 从不解释指令

    mov di, year
    

    作为对 ram 位置的访问。

    .....

    通常堆栈指针 (E)SP 仅用于使用我们的堆栈。 如果我们使用调用指令,那么调用者的地址会被压入栈中,所以如果我们在这个子程序结束时使用 ret 指令,那么地址会从栈中弹出,并且 programmcounter 会被设置为调用指令之后的下一条指令。

    但是,如果我们暂时不使用堆栈,那么我们可以将堆栈指针的地址保存到 ram 位置,以供免费使用堆栈指针。 最后,我们可以将旧地址从 ram 位置取回到堆栈指针中。

    提示:在指令中使用 (E)SP 或 E(BP) 作为地址寄存器,标准段寄存器是“SS”而不是“DS”。

    mov [bp], ax   ; SS:BP
    mov [sp], ax   ; SS:SP
    mov ax, [bp]   ; SS:BP
    mov ax, [sp]   ; SS:SP
    
    mov [si], ax   ; DS:SI
    mov [di], ax   ; DS:DI
    mov [bx], ax   ; DS:BX
    mov ax, [si]   ; DS:SI
    mov ax, [di]   ; DS:DI
    mov ax, [bx]   ; DS:BX
    

    ..

    我不知道为什么会出现这种访问冲突。但是,我认为在使用 SP 之前将 ESP 设置为零可以解决此问题。我认为最好先保存堆栈指针的地址,最后再取回这个地址。

    德克

    【讨论】:

    • 这是 32 位代码;用一些随机数据(不是指针)值覆盖 ESP 显然会导致错误!我猜 OP 不知道 (E)SP 是堆栈指针。您的 16 位寻址模式示例对 Irvine32 问题没有用,[sp] 无论如何也无效。 [esp] 作为 32 位寻址模式有效。
    【解决方案2】:

    我发现了错误。就是这一行:

    mov sp, day
    

    在此之前我没有将esp 设置为零,这就是程序显示访问冲突的原因。

    【讨论】:

    • 这是不正确的。在设置目标寄存器之前设置它不可能与访问冲突有关。访问冲突几乎肯定是由访问espprevious 指令引起的。虽然我不确定为什么归零会有所帮助。访问地址 0 的内存不会特别有用。
    • 问题确实在此说明之前有一个mov esp, 0。事实上(并用临时数据覆盖堆栈指针!!)可能是为什么你以后会遇到错误,也许是当call exit 尝试存储返回地址时到[esp]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-15
    • 2020-09-04
    • 2012-12-05
    • 2013-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多