Как я могу сделать так, чтобы моя программа не зависала? - PullRequest
0 голосов
/ 08 мая 2018

Я не понимаю, почему Windows не может запустить эту программу без сбоев, более того, значок «щит» (режим администратора) вставлен в значок исполняемой программы. Вот мой код (ассемблер FASM, x86-64):

format PE
entry main

foo:
        push ebp
        mov ebp, esp
        enter 3, 0
        mov BYTE [ebp-1], al
        mov DWORD [ebp-8], edi
        mov DWORD [ebp-12], esi
        pop ebp
        leave
        ret
main:
        mov ebp, esp
        mov DWORD [ebp-4], edi
        mov DWORD [ebp-16], esi
        mov al, 97
        mov edi, 43
        mov esi, 76
        call foo
        pop ebp
        ret

Код кажется мне правильным, я не думаю, что это проблема, может быть, некоторые пропущенные инструкции? Я не знаю ...

PS: Странный эффект: когда я меняю каталог программы (который по умолчанию на рабочем столе), щит исчезает ... Я не очень понимаю ...

Примечание: может быть, для вас это очевидно, но для меня это не так. И мои интернет-поиски не нашли ничего убедительного.

[Редактировать код 1]:

Пример другой, еще более упрощенной программы, которая вылетает без видимой причины:

format PE console

org 100h

mov ah,09
mov dx,msg
int 21h
mov ah,08
int 21h
int 20h
msg db "hello world!$"

[Изменить код 2]:

format PE
entry main

main:
        push ebp
        mov ebp, esp
        mov DWORD [ebp-4], edi
        mov DWORD [ebp-16], esi
        mov edi, 8
        call square
        pop ebp
        ret
square:
        push ebp
        mov ebp, esp
        mov DWORD [ebp-4], edi
        pop ebp
        ret   

1 Ответ

0 голосов
/ 12 июня 2018

Итак, вы пытаетесь установить фрейм стека двумя различными независимыми способами - на enter/leave и push/pop. И в результате вы просто путаете стек, поэтому программа возвращает неправильный адрес в инструкции ret.

Используйте только один из этих методов и не забудьте установить код выхода:

Вариант 1

format PE
entry main

foo:
        enter 12, 0
        mov  BYTE [ebp-1], al
        mov  DWORD [ebp-8], edi
        mov  DWORD [ebp-12], esi
        leave
        ret
main:
        enter 16, 0
        mov  DWORD [ebp-4], edi
        mov  DWORD [ebp-16], esi
        mov  al, 97
        mov  edi, 43
        mov  esi, 76
        call foo
        leave
        xor  eax, eax    ; exit code
        ret

Вариант 2

format PE
entry main

foo:
        push ebp
        mov  ebp, esp
        sub  esp, 12
        mov  BYTE [ebp-1], al
        mov  DWORD [ebp-8], edi
        mov  DWORD [ebp-12], esi
        mov  esp, ebp
        pop  ebp
        ret
main:
        push ebp
        mov  ebp, esp
        sub  esp, 16
        mov  DWORD [ebp-4], edi
        mov  DWORD [ebp-16], esi
        mov  al, 97
        mov  edi, 43
        mov  esi, 76
        call foo
        mov  esp, ebp
        pop  ebp
        xor  eax, eax    ; exit code
        ret

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

P.S. Ваш пример DOS также работает, но вам нужно скомпилировать его с немного различными опциями:

format binary as "com"

org 100h

mov ah,09
mov dx,msg
int 21h
mov ah,08
int 21h
int 20h
msg db "hello world!$"

Теперь скомпилируйте и запустите файл результата .com в DOS или используя DosBox в Windows или Linux:

$dosbox myprog.com
...