Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 如何使我的程序不崩溃?_Assembly_Fasm - Fatal编程技术网

Assembly 如何使我的程序不崩溃?

Assembly 如何使我的程序不崩溃?,assembly,fasm,Assembly,Fasm,我不明白为什么Windows不能在不崩溃的情况下运行这个程序,而且在可执行程序图标上插入了“屏蔽”图标(管理员模式)。这是我的代码(FASM汇编程序,x86-64): 代码对我来说似乎是正确的,我不认为这是问题所在,可能是一些缺少的指令?我不知道 PS:奇怪的效果:当我更改程序的目录(默认在桌面上)时,屏蔽消失了。。。我真的不明白 注:也许对你来说这很明显,但对我来说不是。我的网络搜索没有发现任何结论 [代码编辑1]: 另一个程序的示例,更为简化,无明显原因崩溃: format PE conso

我不明白为什么Windows不能在不崩溃的情况下运行这个程序,而且在可执行程序图标上插入了“屏蔽”图标(管理员模式)。这是我的代码(FASM汇编程序,x86-64):

代码对我来说似乎是正确的,我不认为这是问题所在,可能是一些缺少的指令?我不知道

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   

嗯,您正在尝试以两种不同的独立方式设置堆栈帧-通过
enter/leave
push/pop
。因此,您只是弄乱了堆栈,因此程序在
ret
指令上返回了错误的地址

仅使用以下方法之一,不要忘记设置退出代码:

变式1 变式2 这两种变体都不会崩溃,并且会正确终止,尽管它们实际上没有任何用处。你到底想达到什么目的

另外,您的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

猜测一下:您正在交错
leave
pop
。我猜这会把堆栈搞得一团糟,
ret
会失败。@DavidWohlferd:我也想过,但结果是,即使是比这个更简单的程序也会崩溃,甚至不使用leave或enter。发布更简单的代码。这一个也恰好使用了堆栈指针下的内存,这可能是崩溃的原因之一。另外,如果您真的处于64位模式,那么使用32位指针不是最好的主意。不过,我不知道windows将堆栈放在哪里。@Jester:在这里,我编辑了这个问题,使另一个程序出现,它不使用pop/push/LEVE/ret/enter,但仍然崩溃。这可能与
格式PE控制台有关吗?
?这是一个使用旧DOS中断的16位代码。难怪会崩溃。问题不是混合拆卸方法,而是重复两次。您可以使用
leave
拆下由
push ebp
/
mov ebp,esp
创建的堆栈帧。如果ESP尚未指向保存的EBP值,则gcc会这样做。(
enter
很慢,但与
mov
/
pop
相比,
leave
只额外增加1个uop)@PeterCordes即使创建堆栈帧两次,如果嵌套正确也不会导致崩溃。但实际上,OP并不完全理解堆栈是如何工作的,以及为什么我们需要创建堆栈帧。我想上次查看时,我没有注意到OP在其中一个版本中有
enter
。但是,是的,看起来完全不理解这样使用它的一部分。不过,如果您的回答建议完全忽略
enter
,并始终使用
push
/
mov
(带有可选的
子esp
push
)来创建堆栈帧,我会更高兴<如果您在code golf中需要堆栈框架,则code>enter可能很有用,但我不认为像
loop
enter
leave
这样的“高级”指令有助于初学者了解堆栈。@PeterCordes正是因为push/mov变体更清晰,我将其添加到了答案中。但在我看来,仅仅因为功能更复杂而忽略这些功能是错误的。至少OP已经对进入/离开有所了解。还要注意,这个示例实际上非常愚蠢,因为它根本不需要任何堆栈帧。我甚至无法说出OP希望这段代码做什么。我的目标只是展示如何使代码正确终止。我是说,如果我是为初学者授课,我不会提到
loop
enter
。ISA ref手册适用于任何想去挖掘并找到它们的人,或其他复杂的东西,如
rep movsb
shld
pusha
xlat
或任何其他他们不需要的指令(或某些指令)。但你是对的,如果他们已经在询问进入/离开的问题,你不应该在回答中遗漏它。
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
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!$"
$dosbox myprog.com