I am busy programming a win32 program in assembly with a form and buttons... The problem is windows modify my variables in ram. The place were a store my hInstance and hwnd variables. I have found a workaround, but it is not an elegant solution. I would like to know why windows modify my variables and also were can I find documentation which describe the start up of an application.
MyWndProc:
push EBP
mov EBP, ESP
mov eax, [EBP + 12]
cmp eax, WM_DESTROY
jne MyWndProc_j2
push 0
call PostQuitMessage
jmp MyWndProc_j1
MyWndProc_j2:
cmp eax, WM_CREATE
jne MyWndProc_j1
mov eax, [EBP+8]
push eax
call CreateControls
add esp, 4
MyWndProc_j1:
mov eax, [EBP + 20]
push eax
mov eax, [EBP + 16]
push eax
mov eax, [EBP + 12]
push eax
mov eax, [EBP + 8]
push eax
call DefWindowProcA
pop EBP
ret
segment .data
Wtitle db 'My Window',0
ClassName db 'myWindowClass',0
editClass db 'EDIT',0
buttonName db 'OK',0
buttonClass db 'BUTTON',0
textName db 'My textbox',0
textClass db 'edit',0
formEdit db 'This is just a mem test', 0
windowsVar1 dd 0
windowsVar2 dd 0
windowsVar3 dd 0
windowsVar4 dd 0
windowsVar5 dd 0
windowsVar6 dd 0
windowsVar7 dd 0
windowsVar8 dd 0
aMsg dd 0
hwnd dd 0
hwnd2 dd 0
hwnd3 dd 0
hInstance dd 0
old_proc dd 0
nCmdShow dd 0
hfDefault dd 0
MyWndProc is the callback function from windows. At the 27'th call from windows, it modify the last 7 variables. If I switch the position of the last 8 variables with windowsVarx, then it still modifies hwnd, hwnd2 ... without modifying windowsVarx. Where x is from 1 to 8
CreateControls:
push EBP
mov EBP, ESP
push 0
push 0
call GetModuleHandleA
push eax
push IDC_MAIN_BUTTON
mov eax, [EBP+8] ;hwnd
push eax
push 24
push 100
push 220
push 50
mov eax, WS_CHILD
or eax, BS_DEFPUSHBUTTON
or eax, WS_TABSTOP
or eax, WS_VISIBLE
push eax
push buttonName
push buttonClass
push 0
call CreateWindowExA
mov [hwnd2], eax
push DEFAULT_GUI_FONT
call GetStockObject
mov [hfDefault], eax
push 0
mov eax, [hfDefault]
push eax
push WM_SETFONT
mov eax, [hwnd2]
push eax
call SendMessageA
push 0
push 0
call GetModuleHandleA
push eax
push IDC_MAIN_EDIT
mov eax, [EBP+8] ;hwnd
push eax
push 100
push 200
push 100
push 50
mov eax, WS_CHILD
or eax, ES_MULTILINE
or eax, ES_AUTOVSCROLL
or eax, ES_AUTOHSCROLL
or eax, WS_VISIBLE
push eax
push 0
push editClass
push WS_EX_CLIENTEDGE
call CreateWindowExA
mov [hwnd3], eax
push 0
mov eax, [hfDefault]
push eax
push WM_SETFONT
mov eax, [hwnd3]
push eax
call SendMessageA
push Wtitle
push 0
push WM_SETTEXT
mov eax, [hwnd3]
push eax
call SendMessageA
pop EBP
ret
The following function is the message loop, which collect and dispatch.
MyMessageLoop:
push 0
push 0
push 0
push aMsg
call GetMessageA
cmp eax, 0
je MyMessageLoop_j1
push aMsg
call TranslateMessage
push aMsg
call DispatchMessageA
jmp MyMessageLoop
MyMessageLoop_j1:
ret
Your problem explanation isn't really clear. But you should remember that by calling a system call you may indeed end up with different values in your registers. I don't know about Windows, but on amd64 Linux, the kernel (which executes the system call) is required only to preserve the values of the registers r12 and up. The values in all the other registers may be changed and therefore will most probably not be the same after returning from the system call.
In order to remedy that, simply store the variables on your function's stack before calling the system.
It might appear that Windows is modifying your data, but as others have pointed out, it's more likely a bug or some other corruption in your code is causing problems.
It's almost impossible for people to determine the runtime behaviour of your entire program from snippets and programming in assembly almost always causes problems rarely seen when higher-level languages are used.
The best advice is to use a debugger and either step through the code or set a data breakpoint on the variables being modified. Data breakpoints are designed to stop your program on the instruction that performs the data modification.
You could also look at what the actual values of the data that are overwriting your variables - it might give you some clue as to where or why the memory is being overwritten.
The reason for people's sarcasm is that in your second sentence you are assuming Windows is to blame for your program not working. In many situations, blaming the Operating System is a good sign that the developer does not understand something or is reluctant to accept that they have made a mistake. The end result is almost always someone else pointing out the mistake.
Where do I start? Your code formatting is very hard to read. Hope a Uni is not teaching you it. Anyways, your WindowProc was VERY wrong. After EVERY message you handle, you DO NOT call DefWindowProc, most of the messages you just return 0 in eax.
After your call to CreateControls, you don't need add esp, 4 as long as at the end of CreateControls you do ret 4 or ret 4 * NumOfParamsPassed.
I fixed your WindowProc and the window now shows. I also removed the many unneeded movs.
MyWndProc:
push ebp
mov ebp, esp
mov eax, dword ptr[ebp + 3 * 4] ; same as [ebp + 12]
cmp eax, WM_CREATE
je _CREATE
cmp eax, WM_CLOSE
je _CLOSE
PassThrough:
push dword ptr[ebp + 5 * 4]; same as [ebp + 20]
push dword ptr[ebp + 4 * 4]; same as [ebp + 16]
push dword ptr[ebp + 3 * 4]; same as [ebp + 12]
push dword ptr[ebp + 2 * 4]; same as [ebp + 8]
call DefWindowProc
jmp _DONE
_CLOSE:
push 0
call PostQuitMessage
jmp _RET0
_CREATE:
push dword ptr[ebp + 2 * 4]
call CreateControls
;add esp, 4
_RET0:
xor eax, eax
_DONE:
pop ebp
ret 4 * 4 ; <----- you were missing this!!!!!
Why are you adding 4 to esp after a call to CreateControls? You are pushing 1 dword onto the stack, does CreateControls not cleanup the stack itself? You wrote that function? If it does adjust the stack with something like ret 4*1 then that add esp, 4 is screwing everything up. That snippet of code does nothing for us, plus there are so many uneeded movs and jmps there
#David Heffernan thanks I just started writing all my programs in Assembly over 10 years ago and well aware of how and what registers need to be preserved and when you DO NOT need to save them, just because a complier saves all registers in the prologue, doesn't mean it's correct.
Related
I'm doing an activity "Create a program that will alert "Good Morning" at 7:00 am" in MASM32 using kernel based programming which mean I need to use peb structure. I already got the base address of the kernel32.dll which I will use in calling API. I also got the address of the API Im going to use which is GetLocalTime.
My problem is on the last part where I will call the GetLocalTime function for getting the time. Now I'm lost on this part, I can't call the SYSTEMTIME which is important in GetlocalTime function. Any advise? thank you!
.386
.model flat, stdcall
OPTION CASEMAP:NONE
.data
stime dd ?
wHour dw ?
.code
Main:
;getting the kernel32 base address
xor ecx, ecx
ASSUME FS:NOTHING
mov eax, fs:[ecx + 30H] ; EAX = PEB
ASSUME FS:ERROR
mov eax, [eax + 0CH] ; EAX = PEB->Ldrs
mov esi, [eax + 14H] ; ESI = PEB->Ldr.InMemOrder
lodsd ; EAX = Second module
xchg eax, esi ; EAX = ESI, ESI = EAX
lodsd ; EAX = Third(kernel32)
mov ebx, [eax + 10H] ; EBX = Base address
;finding the export table of kernel32
mov edx, [ebx + 3CH] ; EDX = DOS->e_lfanew
add edx, ebx ; EDX = PE Header
mov edx, [edx + 78H] ; EDX = Offset export table
add edx, ebx ; EDX = Export table
mov esi, [edx + 20H] ; ESI = Offset namestable
add esi, ebx ; ESI = Names table
xor ecx, ecx ; EXC = 0
;start of getlocaltime function;
;Find GetLocalTime function name
Get_Time:
inc ecx ; Increment the ordinal
lodsd ; Get name offset
add eax, ebx ; Get function name
cmp dword ptr[eax], 4C746547H ; GetL
jnz Get_Time
cmp dword ptr[eax + 4H], 6C61636FH ; ocal
jnz Get_Time
cmp dword ptr[eax + 8H], 656D6954H ; Time
jnz Get_Time
;Find the address of GetLocalTime function
mov esi, [edx + 24H] ; ESI = Offset ordinals
add esi, ebx ; ESI = Ordinals table
mov cx, [esi + ecx * 2] ; Number of function
dec ecx
mov esi, [edx + 1CH] ; Offset address table
add esi, ebx ; ESI = Address table
mov edx, [esi + ecx * 4] ; EDX = Pointer(offset)
add edx, ebx ; EDX = GetLocalTime
;Call GetLocalTime
add esp, 14H ; Cleanup stack
push offset stime ; offset of the address of hello is pushed in the stack memory
call edx ; getlocaltime nasa eax babagsak
;comparing
push wHour
cmp 00402001H.wHour, 37H
end Main
SYSTEMTIME is just a block of 8 words (16-bit integers); you can allocate 8 words, and refer to the Win32 for the order of the fields.
I am new to assembly and am confused how some variables magically obtain values from nowhere, like in this code I have (program shifts by one ASCII code all entered symbols)
.model small
.stack 100h
.data
Enterr db 10, 13, "$"
buffer db 255
number db ?
symb db 255 dup (?)
.code
START:
MOV ax, #data
MOV ds, ax
MOV ah, 10
MOV dx, offset buffer
INT 21h
MOV ah, 9
MOV dx, offset ENTERR
INT 21h
MOV bx, offset symb
MOV cl, number
MOV ch, 0
CMP cx, 0
JE terminate
cycle:
INC byte ptr [bx]
INC bx
LOOP cycle
MOV byte ptr [bx], '$'
MOV ah, 9
MOV dx, offset symb
INT 21h
terminate:
MOV ah, 4Ch
MOV al, 0
INT 21h
END START
Just before the loop, cx has the number of symbols entered, and cycle begins to take pace from there on. This value of cx was obtained when variable "number" is copied to cl. How did variable "number" obtained such a value? Replacing
MOV cl, number
with
MOV cl, [number]
Does not effect the program. Why is that? Does every variable defined by
variable db ?
has the same value, i.e. number of symbols entered?(I am using TASM)
This question already has an answer here:
What is $ in nasm assembly language? [duplicate]
(1 answer)
Closed 9 years ago.
I came across this following code:
SYS_EXIT equ 1
SYS_WRITE equ 4
STDIN equ 0
STDOUT equ 1
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg1
mov edx, len1
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg2
mov edx, len2
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg3
mov edx, len3
int 0x80
mov eax,SYS_EXIT ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg1 db 'Hello, programmers!',0xA,0xD
len1 equ $ - msg1
msg2 db 'Welcome to the world of,', 0xA,0xD
len2 equ $ - msg2
msg3 db 'Linux assembly programming! '
len3 equ $- msg3
with intuition i can make out that len1, len2 and len3 are variables holding the lengths of the three strings and that the $ - operator is fetching the length of it..
but i am not able to understand properly how the syntax to find the length works.. can anyone, please tell me how it does and give me links for further reading, to understand this concept..
Thanks in advance...
$ evaluates to the "current address", so $ - msg1 means "the current address minus the address with the label msg1". This calculates the length of the string that starts at msg1.
Your snippet looks like it might be NASM. Is it? Anyway, NASM has documentation of its special tokens $ and $$.
I am writting an OS and trying to use the PIT. I have a handler written and wrote an ISR entry for the IRQ0 (Interrupt 32). The handler is not being called at all. I am pretty sure I am not putting the ISR entry in right. Any suggestions? Here is my ASM code
mov dword EAX, irq_common_stub
mov byte [_NATIVE_IDT_Contents + 0x100], AL
mov byte [_NATIVE_IDT_Contents + 0x101], AH
mov byte [_NATIVE_IDT_Contents + 0x102], 0x8
mov byte [_NATIVE_IDT_Contents + 0x105], 0x8E
shr dword EAX, 0x10
mov byte [_NATIVE_IDT_Contents + 0x106], AL
mov byte [_NATIVE_IDT_Contents + 0x107], AH
My code to init the PIT is
public static void PIT_Init(uint frequency)
{
uint divisor = 1193180 / frequency;
GruntyOS.IO.Ports.Outb(0x43, 0x36);
byte l = (byte)(divisor & 0xFF);
byte h = (byte)((divisor >> 8) & 0xFF);
GruntyOS.IO.Ports.Outb(0x40, l);
GruntyOS.IO.Ports.Outb(0x40, h);
}
The handler is
public static void HandlePIT()
{
GruntyOS.IO.Ports.Outb(0xA0, 0x20);
GruntyOS.IO.Ports.Outb(0x20, 0x20);
print("Tick: " + Tick.ToString());
Tick++;
}
Which is called from
irq_common_stub:
pusha
mov ax, ds
push eax
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
call System_Void__GruntyOS_Entry_HandlePIT__
pop ebx
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
popa
add esp, 8
sti
iret
Maybe this might help. Its a simple kernel
that is capable of handling IRQs and Exceptions.
http://www.osdever.net/bkerndev/Docs/irqs.htm
http://www.ni.com/white-paper/2874/en
I'm new to programming in any sort of assembly, and since I've heard that NASM-type assembly for Linux is comparatively simple to DOS based assembly, I decided to give it a try.
This is my program thus far:
section .data
opening: db 'Opening file...',10
openingLen: equ $-opening
opened: db 'File opened.',10
openedLen: equ $-opened
bad_params: db 'Usage: writeFile filename.ext',10
bad_paramsLen: equ $-bad_params
not_opened: db 'Unable to open file. Halted.',10
not_openedLen: equ $-not_opened
hello: db 'Hello, this is written to a file'
helloLen: equ $-hello
success: db 'Successfully wrote to file.',10
successLen: equ $-success
section .bss
file: resd 1
section .text
global _start:
_start:
pop ebx ; pop number of params
test ebx,2 ; make sure there are only 2
jne bad_param_list
pop ebx
mov eax,4 ; write out opening file msg
mov ebx,1
mov ecx,opening
mov edx,openingLen
int 80h
mov eax,5 ; open file
pop ebx
mov ecx,64
mov edx,777o ; permissions of file
int 80h
mov dword [file],eax
test dword [file],0
jle bad_open
mov eax,4 ; write successful open message
mov ebx,1
mov ecx,opened
mov edx,openedLen
int 80h
mov ebx,file ; write to file (4 already in eax)
mov ecx,hello
mov edx,helloLen
int 80h
mov eax,6 ; close file
mov ebx,file
int 80h
mov eax,4 ; write successfully written msg
mov ebx,1
mov ecx,success
mov edx,successLen
int 80h
mov eax,1 ; exit
mov ebx,0
int 80h
bad_param_list:
mov eax,4 ; write that params are bad
mov ebx,1
mov ecx,bad_params
mov edx,bad_paramsLen
int 80h
mov eax,1 ; exit with code 1
mov ebx,1
int 80h
bad_open:
mov eax,4 ; write that we couldn't open the file
mov ebx,1
mov ecx,not_opened
mov edx,not_openedLen
int 80h
mov eax,1 ; exit with code 2
mov ebx,2
int 80h
The goal is to write a string of text to a file without library functions; I'm only using the Linux kernel. I had a few problems with missing brackets here and there, and all the rest of mistakes that you'd expect from a noob to assembly, but I think this is mostly under control now.
Here's my issue: From what I know, the first four lines of this program should pop the number of arguments off the stack, jump to bad_param_list if there is not only one parameter (aside from the program name), and pop the program name off the stack.
But this is not what happens. Here's some sample I/O, reformatted for clarity:
$./writeFile
Opening file...
Unable to open file. Halted.
$./writeFile x
Usage: writeFile filename.ext
$./writeFile x x
Usage: writeFile filename.ext
$./writeFile x x x
Opening file...
Unable to open file. Halted.
$./writeFile x x x x
Opening file...
Unable to open file. Halted.
$./writeFile x x x x x
Usage: writeFile filename.ext
$./writeFile x x x x x x
Usage: writeFile filename.ext
What I've noticed is that if you take the number of arguments including the name of the program, divide by 2, and discard the decimal, if the answer is odd, you'll get my usage error, but if the answer is even, you'll get the unable to open error. This is true up until at least 10 arguments!
How the heck did I manage to do this? And how do I get it to have the expected result?
Instead of
test ebx,2
you want
cmp ebx,2
test performs a bitwise AND between the arguments and throws the result away, except for setting the flags. So, in particular ZF will be set if the two arguments have no 1-bits in positions that match. (In your particular case, this works out as setting ZF to the complement of the second-to-lowest bit of ebx).
Conversely cmp subtracts its arguments and throws away the result after setting flags. In that case, ZF will be set if the two arguments are equal.