如何让我的程序不崩溃?

时间:2018-05-08 20:37:10

标签: assembly fasm

我不明白为什么Windows不能在没有崩溃的情况下运行该程序,而且,在可执行程序图标上插入了“shield”图标(管理员模式)。这是我的代码(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 :(得分:3)

嗯,您正尝试以两种不同的独立方式设置堆栈框架 - enter/leavepush/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!$"

现在在DOS中编译并运行结果.com文件或在Windows或Linux中使用DosBox:

$dosbox myprog.com