Язык ассемблера [MASM] Исключительная ошибка - PullRequest
0 голосов
/ 01 ноября 2018

Это мой MASM-код:

.data
  promptMonth BYTE "Enter month ", 0
  promptDay BYTE "Enter day ", 0
  promptYear BYTE "Enter year ", 0
.code
  main PROC
  p1:
    mov edx, OFFSET promptMonth
    call WriteString
    call ReadInt
    mov ebp, eax

  p2:
    mov edx, OFFSET promptDay
    call WriteString
    call ReadInt
    mov esp, eax

  p3:
    mov edx, OFFSET promptYear
    call WriteString
    call ReadInt
    mov edi, eax
  main ENDP       ; Added by edit

По какой-то причине, когда код попадает в функцию «WriteString» в p3, я получаю ошибку

Исключение, выброшенное в 0x00403687 в Project.exe: 0xC0000005:
Нарушение прав доступа к местоположению 0x00000000 ".

Я не понимаю почему, потому что p1 и p2 работают отлично и они почти такой же код, как p3.

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Вы путаете Указатель стека с инструкцией

mov esp, eax 

Почему ты вообще это делаешь?
Помещение возвращаемого значения в EAX в указатель стека является действительно плохой идеей.

Первая попытка поставить EAX на EBP в лучшем случае бесполезна, поэтому пока не дает никакого эффекта.

Но замена Stack Pointer ESP на возвращаемое значение все портит.

Не делай этого!
Неудивительно, что после этого происходит сбой программы (@ p3).
Итак, чтобы исправить вашу программу, сделайте следующее:

Удалить

mov ebp, eax

и

mov esp, eax

из вашего кода.
Это должно исправить ваши основные проблемы.

Последний

mov edi, eax

не влияет на ход программы, поэтому вы можете делать все, что захотите.

0 голосов
/ 01 ноября 2018

esp - регистр указателя стека. На x86, когда вы call функция, стек используется для передачи параметров и адреса возврата.

Когда вы выполняете mov esp, eax, вы устанавливаете указатель стека равным тому, что возвращается из ReadInt (что, как я полагаю, по его названию является предоставленным пользователем значением), которое вы задали как 0.

Код исключения 0xC0000005 является нарушением доступа , поскольку инструкция call WriteString пыталась поместить адрес возврата из вашего вызывающего кода в местоположение 0x00000000, которое является нулевым указателем.

Решение: чтобы сохранить возвращаемое значение от вызова до ReadInt, используйте регистр, отличный от esp.

Кроме того, если вы не знаете, что не используете назначенный регистр указателя кадра (ebp) по прямому назначению, вы также не должны использовать его как регистр общего назначения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...