You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows x64汇编调用CreateProcessA无输出问题求助

问题:Windows x64汇编程序调用CreateProcessA无输出排查

使用NASM和MinGW开发Windows x64平台的进程管理汇编程序,目标是通过CreateProcessA运行cmd.exe,等待其执行完成并获取退出码,但程序始终无任何输出,无法定位原因。

汇编代码

section .data
    ; Command line to execute
    cmd_line db "C:\Windows\System32\cmd.exe", 0

    ; Log messages
    create_process_msg db "Creating process...", 10, 0
    process_done_msg db "Process completed with exit code: %d", 10, 0
    error_msg db "Error: Could not create process.", 10, 0

section .bss
    ; Reserve space for structures
    sin resb 68                     ; STARTUPINFO structure (size 68 bytes)
    pi resb 24                      ; PROCESS_INFORMATION structure (size 24 bytes)
    exit_code resd 1                ; to store the process exit code

section .text
    extern CreateProcessA, WaitForSingleObject, GetExitCodeProcess, printf, ExitProcess, CloseHandle
    global main

main:
    ; Zero out the STARTUPINFO structure
    lea rcx, [rel sin]
    xor rax, rax
    mov rdi, 68                     ; size of STARTUPINFO
    rep stosb

    ; Set the cb member to the size of the structure
    mov dword [rel sin], 68         ; STARTUPINFO.cb = 68

    ; Print message for creating the process
    lea rcx, [rel create_process_msg]
    call printf

    ; Preserve registers before calling CreateProcessA
    push r12
    push r13
    push r10
    push r11

    ; Call CreateProcessA
    lea rcx, [rel cmd_line]         ; lpCommandLine
    xor rdx, rdx                    ; lpApplicationName (NULL)
    xor r8, r8                      ; lpProcessAttributes (NULL)
    xor r9, r9                      ; lpThreadAttributes (NULL)
    mov r10d, 1                     ; bInheritHandles = TRUE
    mov r11d, 0                     ; dwCreationFlags = 0
    lea r12, [rel sin]              ; lpStartupInfo
    lea r13, [rel pi]               ; lpProcessInformation
    sub rsp, 40                     ; Align stack for Windows x64 calling convention
    call CreateProcessA
    add rsp, 40                     ; Restore stack alignment

    ; Restore preserved registers
    pop r11
    pop r10
    pop r13
    pop r12

    ; Check if process creation was successful
    test rax, rax
    jz process_creation_failed

    ; Wait for the process to complete
    mov rcx, [rel pi + 0]           ; pi.hProcess
    mov rdx, -1                     ; INFINITE timeout
    call WaitForSingleObject

    ; Get the exit code of the process
    mov rcx, [rel pi + 0]           ; pi.hProcess
    lea rdx, [rel exit_code]        ; lpExitCode
    call GetExitCodeProcess

    ; Print the exit code
    mov rsi, [rel exit_code]
    lea rdi, [rel process_done_msg]
    xor rax, rax
    call printf

    ; Close process and thread handles
    mov rcx, [rel pi + 0]           ; pi.hProcess
    call CloseHandle
    mov rcx, [rel pi + 8]           ; pi.hThread
    call CloseHandle

    ; Exit the program
    xor ecx, ecx
    call ExitProcess

process_creation_failed:
    ; Print error message
    lea rcx, [rel error_msg]
    call printf

    ; Exit with error code
    mov ecx, 1
    call ExitProcess

已尝试的调试步骤

  • 重定位错误:最初遇到重定位错误,已通过移除rel引用解决。
  • 寄存器覆盖:怀疑rcx被覆盖,添加了寄存器保护,但问题仍存在。
  • 修改.bss段:尝试将.bss段的resb替换为resq,未解决问题。
  • 错误处理:添加错误消息以检测CreateProcessA是否失败,但错误消息也未打印。
  • 栈对齐:严格遵循Windows x64调用约定进行栈对齐,无效果。

观察结果

  • 程序编译链接无错误,但控制台无任何输出。
  • 即使刻意制造错误条件(如进程创建失败),错误消息也未显示。
  • 程序静默执行,无输出导致调试困难。

编译命令与环境

编译命令

nasm -f win64 EX.asm -o EX.o
gcc -m64 -o EX EX.o -lkernel32 -lmsvcrt
.\EX.exe

环境

  • 操作系统:Windows 10 x64
  • 汇编器:NASM
  • 链接器:Mingw-w64

问题根源与修正方案

你的代码存在多个违反Windows x64调用约定和结构初始化的错误,这些错误导致程序崩溃或API调用失败,进而无输出:

1. STARTUPINFO结构初始化错误

rep stosb指令的使用完全错误:该指令要求rdi指向目标内存地址,rcx是填充的字节数,rax是填充值。你的代码把目标地址放到rcx,计数放到rdi,导致内存操作完全混乱,STARTUPINFO结构未被正确清零,后续API调用可能失败。

修正代码:

; Zero out the STARTUPINFO structure
lea rdi, [rel sin]  ; rdi指向目标地址
xor rax, rax        ; 填充值为0
mov rcx, 68         ; 填充68字节
rep stosb

2. CreateProcessA参数顺序完全颠倒

Windows x64下CreateProcessA的参数顺序为:
lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation

你把lpCommandLine放在了第一个参数(rcx)的位置,而正确的第一个参数是lpApplicationName,这直接导致进程创建失败,且后续错误处理的printf调用也因其他问题无法执行。

修正后的CreateProcessA调用:

; Call CreateProcessA
xor rcx, rcx                    ; lpApplicationName = NULL
lea rdx, [rel cmd_line]         ; lpCommandLine
xor r8, r8                      ; lpProcessAttributes = NULL
xor r9, r9                      ; lpThreadAttributes = NULL
mov r10d, 1                     ; bInheritHandles = TRUE
mov r11d, 0                     ; dwCreationFlags = 0
xor rbx, rbx                    ; lpEnvironment = NULL
xor rbp, rbp                    ; lpCurrentDirectory = NULL
lea r12, [rel sin]              ; lpStartupInfo
lea r13, [rel pi]               ; lpProcessInformation
sub rsp, 40                     ; 预留32字节影子空间+8字节对齐+参数空间
mov [rsp+32], r12               ; 第9个参数(影子空间之后)
mov [rsp+40], r13               ; 第10个参数
call CreateProcessA
add rsp, 40                     ; 恢复栈空间

3. printf调用违反Windows x64调用约定

Windows x64下printf的第一个参数(格式字符串)必须放在rcx,第二个参数(%d对应的值)放在rdx,你错误地使用了rsi和rdi,导致printf调用失败。此外,调用printf前必须保证栈是16字节对齐:main函数被C运行时调用时栈是16字节对齐,call指令会压入8字节的返回地址,所以需要先调整栈对齐。

修正后的printf调用:

; Print message for creating the process
sub rsp, 8                      ; 调整栈到16字节对齐
lea rcx, [rel create_process_msg]
call printf
add rsp, 8                      ; 恢复栈

; ... 中间代码省略 ...

; Print the exit code
sub rsp, 8
lea rcx, [rel process_done_msg]
mov edx, [rel exit_code]        ; %d对应32位整数,用edx即可
xor rax, rax                    ; 无浮点数参数,rax置0
call printf
add rsp, 8

; ... 错误处理中的printf同样需要调整对齐 ...
process_creation_failed:
    ; Print error message
    sub rsp, 8
    lea rcx, [rel error_msg]
    call printf
    add rsp, 8

4. 栈对齐与影子空间处理

Windows x64调用约定要求:调用函数前,栈必须是16字节对齐,且要为被调用函数预留32字节的影子空间(即使函数不需要这么多参数)。你在调用CreateProcessA时预留了40字节(32字节影子+8字节对齐),这部分是对的,但参数传递时要把第9、10个参数放在影子空间之后。


修正后的完整代码

section .data
    ; Command line to execute
    cmd_line db "C:\Windows\System32\cmd.exe", 0

    ; Log messages
    create_process_msg db "Creating process...", 10, 0
    process_done_msg db "Process completed with exit code: %d", 10, 0
    error_msg db "Error: Could not create process.", 10, 0

section .bss
    ; Reserve space for structures
    sin resb 68                     ; STARTUPINFO structure (size 68 bytes)
    pi resb 24                      ; PROCESS_INFORMATION structure (size 24 bytes)
    exit_code resd 1                ; to store the process exit code

section .text
    extern CreateProcessA, WaitForSingleObject, GetExitCodeProcess, printf, ExitProcess, CloseHandle
    global main

main:
    ; Zero out the STARTUPINFO structure
    lea rdi, [rel sin]
    xor rax, rax
    mov rcx, 68
    rep stosb

    ; Set the cb member to the size of the structure
    mov dword [rel sin], 68         ; STARTUPINFO.cb = 68

    ; Print message for creating the process
    sub rsp, 8
    lea rcx, [rel create_process_msg]
    call printf
    add rsp, 8

    ; Preserve non-volatile registers before calling CreateProcessA
    push r12
    push r13
    push rbx
    push rbp

    ; Call CreateProcessA
    xor rcx, rcx                    ; lpApplicationName = NULL
    lea rdx, [rel cmd_line]         ; lpCommandLine
    xor r8, r8                      ; lpProcessAttributes = NULL
    xor r9, r9                      ; lpThreadAttributes = NULL
    mov r10d, 1                     ; bInheritHandles = TRUE
    mov r11d, 0                     ; dwCreationFlags = 0
    xor rbx, rbx                    ; lpEnvironment = NULL
    xor rbp, rbp                    ; lpCurrentDirectory = NULL
    lea r12, [rel sin]              ; lpStartupInfo
    lea r13, [rel pi]               ; lpProcessInformation
    sub rsp, 40                     ; 预留32字节影子空间+8字节对齐+参数空间
    mov [rsp+32], r12
    mov [rsp+40], r13
    call CreateProcessA
    add rsp, 40

    ; Restore non-volatile registers
    pop rbp
    pop rbx
    pop r13
    pop r12

    ; Check if process creation was successful
    test rax, rax
    jz process_creation_failed

    ; Wait for the process to complete
    mov rcx, [rel pi + 0]           ; pi.hProcess
    mov rdx, -1                     ; INFINITE timeout
    call WaitForSingleObject

    ; Get the exit code of the process
    mov rcx, [rel pi + 0]           ; pi.hProcess
    lea rdx, [rel exit_code]        ; lpExitCode
    call GetExitCodeProcess

    ; Print the exit code
    sub rsp, 8
    lea rcx, [rel process_done_msg]
    mov edx, [rel exit_code]
    xor rax, rax
    call printf
    add rsp, 8

    ; Close process and thread handles
    mov rcx, [rel pi + 0]           ; pi.hProcess
    call CloseHandle
    mov rcx, [rel pi + 8]           ; pi.hThread
    call CloseHandle

    ; Exit the program
    xor ecx, ecx
    call ExitProcess

process_creation_failed:
    ; Print error message
    sub rsp, 8
    lea rcx, [rel error_msg]
    call printf
    add rsp, 8

    ; Exit with error code
    mov ecx, 1
    call ExitProcess

内容的提问来源于stack exchange,提问作者kavi castelo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 04:12:02