push / pop eax给了我"非法指令"在编译时

时间:2016-06-07 05:46:13

标签: assembly x86-64 pop fasm

我刚开始使用fasm / x86编程,我开始使用64位样本作为我的项目目标,我需要一些64位xeons。

我从PE64DEMO开始并修改它以添加一个循环,但它在第一次迭代后失败(因为我可以在线收集)Windows api函数可以更改寄存器而不是恢复它们。我也读过我应该保存我需要自己从堆栈中推送和弹出的东西,我评论了推送和弹出,如果我取消注释它们我得到编译时错误说明"错误:非法指令pop eax& #34;

下面的整个文件代码:

; Example of 64-bit PE program

format PE64 GUI
include 'win64a.inc'
entry start


section '.text' code readable executable

  start:
    sub     rsp,8*5         ; reserve stack for API use and make stack dqword aligned



    ; Assembly code representing expr1 here (for instance mov [count], 0)
    mov eax,10
    .for_loop_check:
    ; Assembly code representing expr2 that jumps to .exit_for_loop when false (for instance cmp [count], TOP_VALUE / jae .exit_for_loop when expr2 is "count < TOP_VALUE"). Note that if expr2 is absent then so is the jump.

    cmp eax,0
    jz .exit_for_loop

    ;push eax

    ; body code here
    mov     r9d,0
    lea     r8,[_caption]
    lea     rdx,[_message]
    mov     rcx,0
    call    [MessageBoxA]

    ;pop eax

    ; Assembly code representing expr3 here (for instance inc [count])
    dec eax
    jmp .for_loop_check

    .exit_for_loop:

    mov     ecx,eax
    call    [ExitProcess]

section '.data' data readable writeable

  _caption db 'Win64 assembly program',0
  _message db 'Hello World!',0

section '.idata' import data readable writeable

   library kernel32,'KERNEL32.DLL',\
      user32,'USER32.DLL'

  include 'api\kernel32.inc'
  include 'api\user32.inc'

1 个答案:

答案 0 :(得分:1)

我的代码存在多个问题。

首先,由于Rudy Velthuis评论我的代码是非法的并被fasm正确拒绝,push eaxpop eax在X64中永远无效,因为eax是32位寄存器而X64不允许推送堆栈的32位值。切换到64位寄存器修复了这个问题。

;change
push eax
pop eax
;to
push rax;
pop rax;

有了它,它现在编译并允许我保持我的注册在整个调用,但代码现在在Windows API中段错误。正如Michael Petch所说,这是因为一旦我推送到堆栈,我打破了以前完成的对齐,而Windows 64要求堆栈为16字节对齐,但是不是修复对齐,解决方案很简单,使用非易失性寄存器在Windows X64 ABI中描述的那些并丢弃使用堆栈进行此操作。

带有更改的最终代码:

format PE64 GUI
include 'win64a.inc'
entry start

section '.text' code readable executable

  start:
        sub     rsp,8*5         ; reserve stack for API use and make stack dqword aligned

        ;use rbx as counter as it is preserved across windows API calls
        mov rbx,10

        .for_loop_check:

        cmp rbx,0
        je .exit_for_loop

        mov     r9d,0
        lea     r8,[_caption]
        lea     rdx,[_message]
        mov     rcx,0
        call    [MessageBoxA]

        ;no more pushing and poping to the stack required, rbx is guaranteed to be unmodified by the windows API

        dec rbx
        jmp .for_loop_check

        .exit_for_loop:

        mov     ecx,eax
        call    [ExitProcess]

section '.data' data readable writeable

  _caption db 'Win64 assembly program',0
  _message db 'Hello World!',0

section '.idata' import data readable writeable

  library kernel32,'KERNEL32.DLL',\
          user32,'USER32.DLL'

  include 'api\kernel32.inc'
  include 'api\user32.inc'