Win32 API: Child windows with different images - winapi

I was given a assignment at the university: to write a game in MASM. I chose a game the type of "three in a row". Objects in the game are some sweets: ice cream, lollipop, etc. But I have a problem. I don't know how to make child windows with different images. I've tried, but nothing is working. Maybe someone knows how to implement this? Any help is appreciated. Even in C/C++. I would be glad if someone just explain to me in words how to do it. The main thing for me is to understand the concept.
I have
But I need this

Of course you have JUST ONE IMAGE, because hBit IS A GLOBAL VARIABLE, hBit is overwritten in all calls to CreateSweetsWindow, in fact: it retains last image loaded.
I suggest you add hBit to SweetsWindowStruct struct:
SweetsWindowStruct struct
stype SWEETSTYPE ?
sweetsID DWORD ?
hBit HBITMAP ?
SweetsWindowStruct ends
And remove global hBit (line 44 in your sweets.asm file), you must change WM_PAINT code like this:
.elseif [iMsg] == WM_PAINT
invoke BeginPaint, [hwnd], addr ps
mov [hdc], eax
invoke CreateCompatibleDC, hdc
mov [hMemDC], eax
SweetsWindowStruct *sws;// sorry show you in c++
sws = (SweetsWindowStruct*)GetWindowLong(hwnd, GWL_USERDATA);
HBITMAP hBit = sws->hBit;
invoke SelectObject, hMemDC, [hBit]
mov [oldDC], eax
Other issue: i think you have a error, where you say:
invoke SetWindowLong, [hwnd], 0, addr [sws]
it must be:
invoke SetWindowLong, [hwnd], GWL_USERDATA, addr [sws]
Please check that

Related

Why doesn't SASM's debugger show the value of a "result" variable updating after a store?

I'm trying to run a simple code in assembly - I want to save an address to memory.
I'm moving the address into a register and then moving it into the memory, but for some reason the memory isn't updated.
.data
str1: .asciz "atm course number is 234118"
str2: .asciz "234118"
result: .space 8
.text
.global main
main:
xorq %rax, %rax
xorq %rbx, %rbx
leaq str1, %rax
mov %rax, result(,%rbx,1)
ret
What am I doing wrong?
Your debugger is looking at the wrong instance of result. Your code was always fine (although inefficient; use mov %rax, result(%rip) and don't zero an index, or use mov %rax, result(%rbx,,) to use the byte offset as a "base", not "index", which is more efficient).
glibc contains several result symbols, and in GDB info var result shows:
All variables matching regular expression "result":
Non-debugging symbols:
0x000000000040404b result # in your executable, at a normal static address
0x00007ffff7f54f20 result_type
0x00007ffff7f821b8 cached_result
0x00007ffff7f846a0 result # in glibc, at a high address
0x00007ffff7f85260 result # where the dynamic linker puts shared libs
0x00007ffff7f85660 result
0x00007ffff7f86ab8 result
0x00007ffff7f86f48 result
When I do p /x &result to see what address the debugger resolved that symbol to, I get one of the glibc instances, not the instance in your .data section. Specifically, I get 0x7ffff7f85660 as the address, with the content = 0.
When I print the value with a cast to p /x (unsigned long)result, or dump the memory with GDB's x command, I find a 0 there after the store.
(gdb) x /xg &result
0x7ffff7f85660 <result>: 0x0000000000000000
It looks like your system picked a different instance, one that contained a pointer to a libc address or something. I can't copy-paste from your image. These other result variables are probably static int result or whatever inside various .c files in glibc. (And BTW, that looks like a sign of poor coding style; usually you want to return a value instead of set a global or static. But glibc is old and/or maybe there's some justification for some of those.)
Your result: is the asm a compiler would make for static void* result if it didn't get optimized away. Except it would put it in .bss instead of .data because it's zero-initialized.
You're using SASM. I used GDB to get more details on exactly what's going on. Looking at the address of result in SASM's debug pane might have helped. But now that we've identified the problem using GDB, we can change your source to fix it for SASM.
You can use .globl result to make it an externally-visible symbol so it "wins" when the debugger is looking for symbols.
I added that and compiled again with gcc -g -no-pie store.s. It works as expected now, with p /x (unsigned long)result giving 0x404028

How do I get address of class member function by asm in GCC?

guys! I have a problem. How do I get address of class member function by asm in GCC?
In VS2012, we can do below code to get address.
asm {mov eax, offset TEST::foo}
But, in GCC?
__asm__ __volatile__(
"movq offset %1, %%rdi"
"movq %%rdi, %0"
:"=r"(addr)
:"r"(&TEST::foo)
);
It failed...
AT&T syntax doesn't use the offset keyword. And besides, you've asked the compiler to put &TEST::foo in a register already.
__asm__ (
"mov %1, %0"
:"=r"(addr)
:"r"(&TEST::foo)
);
Or better:
__asm__ ( "" // no instructions
:"=r"(addr)
:"0"(&TEST::foo) // same register as operand 0
);
Or even better: addr = &TEST::foo; https://gcc.gnu.org/wiki/DontUseInlineAsm for this, because it stops the compiler from knowing what's going on.
But if you are going to use inline asm, make sure you let the compiler do as much for you as it can. Use constraints to tell it where you want the input, and where you left the output. If the first or last instruction of an inline-asm statement is a mov, usually that means you're doing it wrong. (See the inline-assembly tag wiki for some links to guides on how to write GNU C inline asm that doesn't suck.
Bugs in your original: you didn't declare a clobber on RDI, so the compiler will still assume you didn't modify it.
You don't need volatile if the only reason to run the code in the asm statement is to produce the output operands, not for side effects. Leaving out volatile lets the compiler optimize around it, and even drop it entirely if the output is unused.

How to access local variables in GCC inline assembly while changing sp?

Consider the following simplified example function:
void foo(void) {
int t;
asm("push %0\n\t"
"push %0\n\t"
"call bar"
:
: "m" (t)
:
);
}
If I compile it with Cygwin x86 gcc 4.8.3 without optimization, the push instructions become:
push -4(%ebp)
push -4(%ebp)
This is good. The problem happens with -O:
push 12(%esp)
push 12(%esp)
This is clearly wrong. The first push changes esp, and the second push then accesses the wrong location. I have read that adding "%esp" to the clobber list should fix it, but it does not help. How can I make GCC use a frame pointer or properly consider esp changes?
(Assume that returning from the bar function will set esp to the value it had before the asm statement. I just need to call a thiscall function and am using inline assembly for that.)
I can simply use __attribute__((optimize("-fno-omit-frame-pointer"))) to prevent the problem-causing optimization in this one function. This might be the best solution. – dreamlayers

80x86 assembler printf contents of memory

I have to write Windows program in x86 assembler (I'm using flat assembler) which will be printing contents of predefined memory. I wrote:
format PE console 4.0
include "win32ax.inc"
start:
mov eax, [0x00850095]
cinvoke printf,formatstring, eax
invoke Sleep,-1
formatstring db "%#x"
section '.idata' import data readable
library msvcrt,'msvcrt.dll',\
kernel32,'kernel32.dll'
import msvcrt,printf,'printf'
import kernel32,Sleep,'Sleep'
It's not working :C; can you help me with that?
Your format string is not quite correct. "%#x" should probably be "%08X" if you want to print the value of eax. If you want to print the value located at the address in eax then you need to load the value pointed to by eax and pass that to printf.
The %x format specifier to printf expects an int passed in the varargs, so if you want to print one byte at a time, you need to load a byte, zero-extended, into eax and then pass eax to printf.

How to get the name/description of an exception?

How do you get the name and/or description of an SEH exception without having to hard-code the strings into your application?
I tried to use FormatMessage(), but it truncates the message sometimes, even if you specify to ignore inserts:
__asm { // raise access violation
xor eax, eax
mov eax, [eax]
}
Raises an exception with the code 0xC0000005 (EXCEPTION_ACCESS_VIOLATION).
char msg[256];
FormatMessageA(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
GetModuleHandleA("ntdll.dll"), 0xC0000005,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
msg, sizeof(msg), NULL);
Fills msg with the truncated string: "The instruction at 0x".
Structured exception codes are defined through NTSTATUS numbers. Although someone from MS suggests using FormatMessage() to convert NTSTATUS numbers to strings, I would not do this. Flag FORMAT_MESSAGE_FROM_SYSTEM is used to convert result of GetLastError() into a string, so it makes no sense here. Using flag FORMAT_MESSAGE_FROM_HMODULE along with ntdll.dll will lead to incorrect results for some codes. E.g., for EXCEPTION_ACCESS_VIOLATION you will get The instruction at 0x, which is not very informative :) .
When you look at the strings that are stored in ntdll.dll it becomes obvious that many of them are supposed to be used with the printf() function, not with the FormatMessage(). For example, the string for EXCEPTION_ACCESS_VIOLATION is:
The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.
%0 is treated by FormatMessage() as the escape sequence meaning message terminator, not an insert. Inserts are %1 to %99. That's why flag FORMAT_MESSAGE_IGNORE_INSERTS does not make any difference.
You might want to load the string from ntdll.dll and pass it to vprintf() but you will need to prepare arguments exactly as the string specifies (e.g. for EXCEPTION_ACCESS_VIOLATION it's unsigned long, unsigned long, char*). And this approach has major drawback: any change in the number, order or size of arguments in ntdll.dll may break your code.
So it's safer and easier to hard code the strings into your own code. I find it dangerous to use strings prepared by someone else without coordination with me :) and moreover for other function. This is just one more possibility for malfunction.
Does this apply?
http://www.winehq.org/pipermail/wine-devel/2001-May/000801.html

Resources