why is bitblt throwing an exception - winapi

Im trying to create a program to output a picture to the screen, but when i do visual studio masm throws the exception Exception thrown at 0x00007FFEA0F15ADE (gdi32.dll) in assemblydraw.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF. and i dont know why this is happening or how to fix it.
Main code block
includelib user32.lib
include externals.asm
.data
include variables.asm
include pic.asm
.code
start proc
mov holder, rsp
and rsp, -16
sub rsp, 32
xor rcx, rcx
getdcfail:
call __imp_GetDC
cmp rax, 0
je getdcfail
mov screendc, rax
mov rbx, 2000000000
mov rcx, screendc
lea rdx, bitmapinfo
mov r8, 4; cbm_init
lea r9, pic1colorbytes
push rdx
push 0
call __imp_createdibitmap
mov picdc, rax
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
dec rbx
nop
nop
nop
nop
nop
nop
nop
nop
nop
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_DeleteObject
xor rcx, rcx
call __imp_ExitProcess
mov rsp, holder
ret
start endp
end
Externals.asm
extrn __imp_GetDC:qword
extrn __imp_ReleaseDC:qword
extrn __imp_GetDesktopWindow:qword
extern __imp_ExitProcess:QWORD
extern __imp_SetDIBitsToDevice:qword
extern __imp_BitBlt:qword
extern __imp_CreateDIBitmap:qword
extern __imp_DeleteObject:qword
First part of pic.asm, a dib created by photoshop, and translated to hex codes to be put in my program
align qword
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

Related

Why is D2D1CreateFactory Sending an error message in assembly

I have a program so far all it does is tries to create a D2D1Factory but i get the error message E_NOINTERFACE and I thought I had the right IID_ID2D1Factory and I've checked multiple times in multiple places. Can somebody tell me why its failing and/or how to fix it.
My code
include externals.asm
include wincons.asm
include vtable.asm
.data
include variables.asm
;include pic.asm
include riid.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
mov rcx, D2D1_FACTORY_TYPE_SINGLE_THREADED
lea rdx, IID_ID2D1Factory
mov r8, D2D1_DEBUG_LEVEL_NONE
lea r9, ID2D1Factory
call __imp_D2D1CreateFactory
drawscreen:
jnc drawscreen
xor rcx, rcx
call __imp_ExitProcess
mov rsp, rbp
pop rbp
pop r13
pop rbx
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
extern __imp_GetLastError:qword
extern __imp_GetAsyncKeyState:word
extern __imp_D2D1CreateFactory:qword
Variables.asm
align qword
screendc qword ?
picdc qword ?
ID2D1Factory qword ?
Wincons.asm
DIB_RGB_COLORS equ <0>
SRCCOPY equ <0CC0020h>
D2D1_DEBUG_LEVEL_NONE equ <0>
D2D1_FACTORY_TYPE_SINGLE_THREADED equ <0>
And finally riid.asm
IID_IUnknown Dword 000000000h
word 00000h
word 00000h
word 0C000h
byte 000h
byte 000h
byte 000h
byte 000h
byte 000h
byte 046h
IID_ID2D1RenderTarget Dword 02cd90694h
word 012e2h
word 011dch
byte 09fh
byte 0edh
byte 000h
byte 011h
byte 043h
byte 0a0h
byte 055h
byte 0f9h
IID_ID2D1Factory Dword 006152247h
word 06f50h
word 0465ah
word 09245h
byte 011h
byte 08bh
byte 0fdh
byte 03bh
byte 060h
byte 007h
You didn't define the UUID for IID_ID2D1Factory correctly. The problem is that the Microsoft binary encoding of UUIDs requires that the last two components of the UUID {06152247-6f50-465a-9245-118bfd3b6007} be in big-endian format, unlike the first three components which are in little-endian order. So it should be:
IID_ID2D1Factory Dword 006152247h
word 06f50h
word 0465ah
byte 092h
byte 045h
byte 011h
byte 08bh
byte 0fdh
byte 03bh
byte 060h
byte 007h
Instead of defining this UUIDs yourself, it would be easier and less error prone to use the definitions in uuid.lib included in the Windows SDK.

why is setdibits failing in masm assembly

I've been working on outputting a bitmap image to the screen, the bitmap is 50 pixels by 50 pixels, but when i try to draw the bits to a DDB using setdibits it fails and then i get a black box on the screen because the CreateCompatibleBitmap makes a 50 by 50 pixel black bitmap. Does anybody know why SetDIBits is failing or how to fix it.
Main body of my code
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 was a 50 by 50 dib created with photoshop, then all the hex values extracted and allocated as bytes. this is the beginning part of pic.asm, whole thing is 10061 lines long
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 was failing simply because i didn't understand calling conversion fully. I thought when it said "all other parameters are passed to the stack" i thought of the opcode push, but what it meant was setting the parameters by mov with an offset. so when i changed the calling conversion it outputted the bitmap, but in monochrome. I then learned that it was because i was using picdc with createCompatibleBitmap and i instead needed to use screenDC so when i fixed that it outputted properly.
Here is the fixed code, only the main body was changed everything else stayed the same.
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
EDIT: I fixed a few more errors in my code pointed out by Raymond Chen

Unable to display my output as required . I'm trying to program a decimal to binary converter in x86 assembly language in Visual Studio

This
is how my output should look like.
Here is my code:
.586
.MODEL FLAT
;Exit Process PROTO NEAR32 stdcall,dwExitCode:DWORD
INCLUDE io.h
cr EQU 0dh
Lf EQU 0ah
.STACK 4096
.DATA
prompt1 BYTE "Enter the decimal number: ", 0
asciiIn DW 4 DUP (?)
msgLabel BYTE "Result",00h; message Label
msgText BYTE "Your output" ;
BYTE "Decimal: "
asciiDecimal DW 4 DUP (?),10
BYTE "Binary: "
asciiBinary DW 4 DUP(?), 10
BYTE "Hex: "
asciiHex DW 4 DUP (?), 10
decimal WORD 0
STR1 DW 4 DUP (?)
STR2 DW 4 DUP (?)
HEX WORD 0
.CODE
_MainProc PROC
xor eax, eax ; clear eax
xor ebx, ebx ; clear ebx
xor ecx, ecx ; clear ecx
lp : input prompt1, asciiIn, 10 ; prompt user to enter number
atow asciiIn ; convert from ascii to word and store in eax
LEA ESI,STR1
; MOV EAX,NO
MOV BH,00
MOV BL,2
L1:DIV BL
ADD AH,'0'
MOV BYTE PTR[ESI],AH
MOV AH,00
INC ESI
INC BH
CMP AL,00
JNE L1
MOV CL,BH
LEA ESI,STR1
LEA EDI,STR2
MOV CH,00
ADD ESI,ECX
DEC ESI
L2:MOV AH,BYTE PTR[ESI]
MOV BYTE PTR[EDI],AH
DEC ESI
INC EDI
LOOP L2
done :
; output messages
output msgLabel,msgText
wtoa asciiDecimal, asciiIn
output asciiBinary,STR2
wtoa asciiHex, HEX
mov eax, 0
ret
_MainProc ENDP
END

Best way to load a byte for write

To read and then write a byte from and to memory, you can choose between a few options, among them:
Load a 32-bit value, write out a byte:
mov eax, [rdi]
mov byte [rsi], al
Load a byte, write a byte:
mov al, byte [rdi]
mov byte [rsi], al
Load a byte, zero extended, write a byte:
movzx eax, byte [rdi]
mov byte [rsi], al
All the approaches are the same on the write side, but they use different ways of reading the value. Is there any reason to prefer one over the others, particularly performance-wise?

why if the number I enter gets to high it returns the wrong number [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I've got the following code but I can't work out why if the number I enter is too high does it return the wrong number. It might be because of the data types and dividing and multiplying but I can't work out exactly why. if you know of why I would be grateful for the help.
.586
.model flat, stdcall
option casemap :none
.stack 4096
extrn ExitProcess#4: proc
GetStdHandle proto :dword
ReadConsoleA proto :dword, :dword, :dword, :dword, :dword
WriteConsoleA proto :dword, :dword, :dword, :dword, :dword
STD_INPUT_HANDLE equ -10
STD_OUTPUT_HANDLE equ -11
.data
bufSize = 80
inputHandle DWORD ?
buffer db bufSize dup(?)
bytes_read DWORD ?
sum_string db "The number was ",0
outputHandle DWORD ?
bytes_written dd ?
actualNumber dw 0
asciiBuf db 4 dup (0)
.code
main:
invoke GetStdHandle, STD_INPUT_HANDLE
mov inputHandle, eax
invoke ReadConsoleA, inputHandle, addr buffer, bufSize, addr bytes_read,0
sub bytes_read, 2 ; -2 to remove cr,lf
mov ebx,0
mov al, byte ptr buffer+[ebx]
sub al,30h
add [actualNumber],ax
getNext:
inc bx
cmp ebx,bytes_read
jz cont
mov ax,10
mul [actualNumber]
mov actualNumber,ax
mov al, byte ptr buffer+[ebx]
sub al,30h
add actualNumber,ax
jmp getNext
cont:
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov outputHandle, eax
mov eax,LENGTHOF sum_string ;length of sum_string
invoke WriteConsoleA, outputHandle, addr sum_string, eax, addr bytes_written, 0
mov ax,[actualNumber]
mov cl,10
mov bl,3
nextNum:
xor edx, edx
div cl
add ah,30h
mov byte ptr asciiBuf+[ebx],ah
dec ebx
mov ah,0
cmp al,0
ja nextNum
mov eax,4
invoke WriteConsoleA, outputHandle, addr asciiBuf, eax, addr bytes_written, 0
mov eax,0
mov eax,bytes_written
push 0
call ExitProcess#4
end main
Yes, it is plausible that your return value is capped by a maximum value. This maximum is either the BYTE boundary of 255 or the WORD boundary of 65536. Let me explain why, part by part:
mov inputHandle, eax
invoke ReadConsoleA, inputHandle, addr buffer, bufSize, addr bytes_read,0
sub bytes_read, 2 ; -2 to remove cr,lf
mov ebx,0
mov al, byte ptr buffer+[ebx]
sub al,30h
add [actualNumber],ax
In this part you are calling a Win32 API function, which always returns the return value in the register EAX. After it has returned, you assign the lower 8-bits of the 32-bit return value to byte ptr buffer+[ebx], subtract 30h from it. Then you MOV the 8-bit you just modified in AL and the 8-bit from the return-value preserved in AH as a block AX to a WORD variable by add [actualNumber],ax. So AH stems from the EAX return value and is quite of undefined. You may be lucky if it's 0, but that should not be assumed.
The next problem is the following sub-routine:
getNext:
inc bx
cmp ebx,bytes_read
jz cont
mov ax,10
mul [actualNumber]
mov actualNumber,ax
mov al, byte ptr buffer+[ebx]
sub al,30h
add actualNumber,ax
jmp getNext
You are moving the decimal base 10 to the WORD register AX and multiply it by the WORD variable [actualNumber]. So far, so good. But the result of a 16-bit*16-bit MUL is returned in the register pair AX:DX(lower:higher). So your mov actualNumber,ax solely MOVs the lower 16-bits to your variable (DX is ignored, limiting your result to result % 65536). So your maximum possible result is MAX_WORD = 65535. Everything else would just give you the modulo in AX.
After your mov al, byte ptr buffer+[ebx] your overwrite the lower 8-bits of this result with the BYTE pointed to by buffer[ebx] and then subtract 30h from it. Remember: the higher 8-bits of the result still remain in AH, the higher 8-bits of AX.
Then you (re)add this value to the variable actualNumber with add actualNumber,ax. Let me condense these last two paragraphs:
Operation | AX |
| AL AH |
mov actualNumber,ax | ................ |
mov al, byte ptr buffer+[ebx] | ........ AH |
sub al,30h | ....-30h AH |
add actualNumber,ax | ................ |
So, you are modifying the lower 8-bits of AX through AL and then add the higher 8-bits of actualNumber/AH to itself - effectively doubling AH and then adding this to actualNumber like this:
actualNumber = 256 * (2 * AH) + (byte ptr buffer[ebx]-30h) ; I doubt you want that ;-)
These problems may cause several deviations from the desired result.

Resources