为什么 setdibits 在 masm 汇编中失败
why is setdibits failing in masm assembly
我一直致力于将 bitmap image
输出到屏幕,bitmap
是 50 x 50 像素,但是当我尝试将这些位绘制到 DDB
使用 setdibits
它失败了,然后我在屏幕上看到一个黑框,因为 CreateCompatibleBitmap
使 50 x 50 像素变成黑色 bitmap
。有谁知道为什么 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
externals.asm
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>
variables.asm
align qword
holder qword ?
screendc qword ?
picdc qword ?
pic.asm 是用 photoshop 创建的 50 x 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
失败仅仅是因为我没有完全理解调用转换。我想当它说 "all other parameters are passed to the stack" 我想到了 opcode
push
,但它的意思是通过 mov
设置参数并带有偏移量。所以当我更改调用转换时,它输出 bitmap
,但是是单色的。然后我了解到这是因为我正在使用 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 指出的代码中的更多错误
我一直致力于将 bitmap image
输出到屏幕,bitmap
是 50 x 50 像素,但是当我尝试将这些位绘制到 DDB
使用 setdibits
它失败了,然后我在屏幕上看到一个黑框,因为 CreateCompatibleBitmap
使 50 x 50 像素变成黑色 bitmap
。有谁知道为什么 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
externals.asm
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>
variables.asm
align qword
holder qword ?
screendc qword ?
picdc qword ?
pic.asm 是用 photoshop 创建的 50 x 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
失败仅仅是因为我没有完全理解调用转换。我想当它说 "all other parameters are passed to the stack" 我想到了 opcode
push
,但它的意思是通过 mov
设置参数并带有偏移量。所以当我更改调用转换时,它输出 bitmap
,但是是单色的。然后我了解到这是因为我正在使用 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 指出的代码中的更多错误