Итак, вы пытаетесь установить фрейм стека двумя различными независимыми способами - на 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