Winapi 为什么setdibits在masm汇编中失败

Winapi 为什么setdibits在masm汇编中失败,winapi,assembly,x86-64,masm,Winapi,Assembly,X86 64,Masm,我一直在努力将位图图像输出到屏幕上,位图是50像素乘以50像素,但是,当我尝试使用setdibits将位绘制到DDB时,它失败了,然后我在屏幕上看到一个黑框,因为CreateCompatibleBitmap生成一个50×50像素的黑色位图。有人知道为什么SetDIBits失败或者如何修复它吗 我的代码主体 includelib user32.lib include externals.asm include wincons.asm .data include variables.asm incl

我一直在努力将
位图图像
输出到屏幕上,
位图
是50像素乘以50像素,但是,当我尝试使用
setdibits
将位绘制到
DDB
时,它失败了,然后我在屏幕上看到一个黑框,因为
CreateCompatibleBitmap
生成一个50×50像素的黑色
位图。有人知道为什么
SetDIBits
失败或者如何修复它吗

我的代码主体

includelib user32.lib
include externals.asm
include wincons.asm
.data
include variables.asm
include pic.asm
.code
start proc
    mov holder, rsp
    and rsp, -16
    sub rsp, 32
    call __imp_GetDesktopWindow
    mov rcx, rax
getdcfail:
    call __imp_GetDC
    cmp rax, 0
    je getdcfail
    mov screendc, rax
    mov rcx, rax
    call __imp_CreateCompatibleDC
    mov picdc, rax
    mov rcx, rax
    mov rdx, 50
    mov r8, 50
    call __imp_CreateCompatibleBitmap
    mov rcx, picdc
    mov rdx, rax
    mov r13, rax
    mov r8, 0
    mov r9, 50
    lea r12, [pic1colorbytes]
    push r12
    lea r12, [bitmapinfo]
    push r12
    push DIB_RGB_COLORS
    call __imp_SetDIBits
    add rsp, 24
    mov rcx, picdc
    mov rdx, r13
    call __imp_SelectObject
    mov rbx, 10000000
drawscreen:
    mov rcx, screendc
    mov rdx, 0
    mov r8, 0
    mov r9, 50
    push 50
    push picdc
    push 0
    push 0
    push 0CC0020h; srccopy is hex cc0020
    call __imp_bitblt
    add rsp, 40
    dec rbx
    cmp rbx, 0
    jne drawscreen
releasedcfail:
    mov rdx, screendc
    xor rcx, rcx
    call __imp_ReleaseDC
    cmp rax, 0
    je releasedcfail
    ;mov rcx, picdc
    ;call __imp_DeleteDC
    xor rcx, rcx
    call __imp_ExitProcess
    mov rsp, holder
    ret
start endp
end
外部性

extern __imp_GetDC:qword
extern __imp_ReleaseDC:qword
extern __imp_GetDesktopWindow:qword
extern __imp_ExitProcess:QWORD
extern __imp_SetDIBits:qword
extern __imp_BitBlt:qword
extern __imp_CreateDIBitmap:qword
extern __imp_DeleteObject:qword
extern __imp_DeleteDC:qword
extern __imp_CreateCompatibleBitmap:qword
extern __imp_SelectObject:qword
extern __imp_CreateCompatibleDC:qword
extern __imp_GetDesktopWindow:qword
wincons.asm

DIB_RGB_COLORS equ <0>
asm是用photoshop创建的一个50乘50的dib,然后将所有十六进制值提取并分配为字节。这是pic.asm的开始部分,整个过程有10061行

align dword
pic1:
byte 042H
byte 04DH
byte 048H
byte 027H
byte 000H
byte 000H
byte 000H
byte 000H
byte 000H
byte 000H
byte 036H
byte 000H
byte 000H
byte 000H
bitmapinfo:
byte 028H
byte 000H
byte 000H
byte 000H
byte 032H
byte 000H
byte 000H
byte 000H
byte 032H
byte 000H
byte 000H
byte 000H
byte 001H
byte 000H
byte 020H
byte 000H
byte 000H
byte 000H
byte 000H
byte 000H
byte 012H
byte 027H
byte 000H
byte 000H
byte 023H
byte 02EH
byte 000H
byte 000H
byte 023H
byte 02EH
byte 000H
byte 000H
byte 000H
byte 000H
byte 000H
byte 000H
byte 000H
byte 000H
byte 000H
byte 000H
pic1colorbytes:
byte 0FFH
byte 0FFH
byte 0FFH
byte 000H
byte 0FFH
byte 0FFH
byte 0FFH
byte 000H
byte 0FFH
byte 0FFH
byte 0FFH
byte 000H
byte 0FFH
byte 0FFH
byte 0FFH
byte 000H
byte 0FFH
byte 0FFH
byte 0FFH
byte 000H
byte 0FFH
byte 0FFH
byte 0FFH
byte 000H
byte 0FFH
byte 0FFH
byte 0FFH
byte 000H
byte 0FFH
byte 0FFH
byte 0FFH
byte 000H
byte 0FFH
byte 0FFH
byte 0FFH
byte 000H
byte 0FFH
byte 0FFH
byte 0FFH
byte 000H
byte 0FFH
byte 0FFH

SetDIBits
失败仅仅是因为我不完全理解调用转换。当它说“所有其他参数都传递到堆栈”时,我想到了
opcode
push
,但它的意思是通过带偏移量的
mov
设置参数。因此,当我更改调用转换时,它输出了
位图,但是是单色的。然后我了解到,这是因为我使用了
picdc
createCompatibleBitmap
,而我需要使用
screenDC
,所以当我修复时,它输出正确

这是固定的代码,只是主体被更改了,其他的都保持不变

includelib user32.lib
include externals.asm
include wincons.asm
.data
include variables.asm
include pic.asm
.code
start proc frame
    DB 48h
    push rbx
    .pushreg rbx
    push r13
    .pushreg r13
    push rbp
    .pushreg rbp
    sub rsp, 80
    .allocstack 80
    lea rbp, [rsp + 80]
    .setframe rbp, 80
    .endprolog
    call __imp_GetDesktopWindow
    mov rcx, rax
getdcfail:
    call __imp_GetDC
    cmp rax, 0
    je getdcfail
    mov screendc, rax
    mov rcx, rax
    call __imp_CreateCompatibleDC
    mov picdc, rax
    mov rcx, screendc
    mov rdx, 50
    mov r8, 50
    call __imp_CreateCompatibleBitmap
    mov rcx, screendc
    mov rdx, rax
    mov r13, rax
    mov r8, 0
    mov r9, 50
    lea rax, [bitmapinfo + 28h]
    mov qword ptr [rsp + 20h], rax
    lea rax, [bitmapinfo]
    mov qword ptr [rsp + 28h], rax
    mov eax, 0
    mov dword ptr [rsp + 30h], eax
    call __imp_SetDIBits
    mov rcx, picdc
    mov rdx, r13
    call __imp_SelectObject
    mov rbx, 10000000
drawscreen:
    mov rcx, screendc
    mov rdx, 0
    mov r8, 0
    mov r9, 50
    mov qword ptr [rsp + 20h], 50
    mov rax, picdc
    mov qword ptr [rsp + 28h], rax
    mov qword ptr [rsp + 30h], 0
    mov qword ptr [rsp + 38h], 0
    mov qword ptr [rsp + 40h], 0CC0020h; srccopy is hex cc0020
    call __imp_bitblt
    dec rbx
    cmp rbx, 0
    jne drawscreen
releasedcfail:
    mov rdx, screendc
    xor rcx, rcx
    call __imp_ReleaseDC
    cmp rax, 0
    je releasedcfail
    ;mov rcx, picdc
    ;call __imp_DeleteDC
    xor rcx, rcx
    call __imp_ExitProcess
    mov rsp, rbp
    pop rbp
    pop r13
    pop rbx
    ret
start endp
end

编辑:我修复了Raymond Chen指出的代码中的一些错误

GetDIBits返回什么?GetLastError返回什么?我想你是指SetDIBits,SetDIBits返回0。GetLastError返回00000000000036B7,也称为ERROR_SXS_KEY_NOT_found看起来您的BITMAPINFO结构缺少BICLRUSE和BICLR重要字段。我不相信任何东西能生成正确的结构,因为这是一种内存格式,而不是一种定义良好的文件格式。您在错误的位置将参数传递给SetDIBits和BitBlt。此外,您没有声明任何展开代码,这一点尤其令人担忧,因为您也在进行收缩包装,这比更传统的函数展开更复杂。参数不是
push
ed。它们直接存储在堆栈中,从偏移量32开始。请参见第二个链接中的图表。查看约定的最简单方法是编译一些C代码并查看程序集。在
push rbp
之前缺少一个
db 48h
,以确保第一条指令至少有2个字节长。在
push rbp
之后缺少
.pushreg rbp
指令,在
子rsp之后缺少
.allocstack 80
,在
lea rbp,[rsp+80]
之后缺少
.setframe rbp,80
endprolog
。您的代码也无法保留
rbx
寄存器。由于所有的软件约定,x86-64汇编在Windows上非常复杂。
includelib user32.lib
include externals.asm
include wincons.asm
.data
include variables.asm
include pic.asm
.code
start proc frame
    DB 48h
    push rbx
    .pushreg rbx
    push r13
    .pushreg r13
    push rbp
    .pushreg rbp
    sub rsp, 80
    .allocstack 80
    lea rbp, [rsp + 80]
    .setframe rbp, 80
    .endprolog
    call __imp_GetDesktopWindow
    mov rcx, rax
getdcfail:
    call __imp_GetDC
    cmp rax, 0
    je getdcfail
    mov screendc, rax
    mov rcx, rax
    call __imp_CreateCompatibleDC
    mov picdc, rax
    mov rcx, screendc
    mov rdx, 50
    mov r8, 50
    call __imp_CreateCompatibleBitmap
    mov rcx, screendc
    mov rdx, rax
    mov r13, rax
    mov r8, 0
    mov r9, 50
    lea rax, [bitmapinfo + 28h]
    mov qword ptr [rsp + 20h], rax
    lea rax, [bitmapinfo]
    mov qword ptr [rsp + 28h], rax
    mov eax, 0
    mov dword ptr [rsp + 30h], eax
    call __imp_SetDIBits
    mov rcx, picdc
    mov rdx, r13
    call __imp_SelectObject
    mov rbx, 10000000
drawscreen:
    mov rcx, screendc
    mov rdx, 0
    mov r8, 0
    mov r9, 50
    mov qword ptr [rsp + 20h], 50
    mov rax, picdc
    mov qword ptr [rsp + 28h], rax
    mov qword ptr [rsp + 30h], 0
    mov qword ptr [rsp + 38h], 0
    mov qword ptr [rsp + 40h], 0CC0020h; srccopy is hex cc0020
    call __imp_bitblt
    dec rbx
    cmp rbx, 0
    jne drawscreen
releasedcfail:
    mov rdx, screendc
    xor rcx, rcx
    call __imp_ReleaseDC
    cmp rax, 0
    je releasedcfail
    ;mov rcx, picdc
    ;call __imp_DeleteDC
    xor rcx, rcx
    call __imp_ExitProcess
    mov rsp, rbp
    pop rbp
    pop r13
    pop rbx
    ret
start endp
end