This is the code that I use with FASM:
format PE console
entry main
include '..\MACRO\import32.inc'
section '.data' data readable writeable
msg db "привіт!",0dh,0ah,0 ;hi
lcl_set db ?
section '.code' code readable executable
main:
;fail without set locale
push msg
call [printf]
pop ecx
;succeed with set locale
push msg
call _liapnuty
pop ecx
push 0
call [ExitProcess]
_liapnuty:
push ebp
mov ebp, esp
;sub esp, 0
mov ebx,[ebp+8] ; 1st arg addr
mov al, [lcl_set]
or al, al
jnz _liapnuty_rest
call __set_locale
_liapnuty_rest:
push ebx
call [printf]
pop ebx
mov esp, ebp
pop ebp
ret 0
__set_locale:
mov al, [lcl_set]
or al, al
jnz __set_locale_rest
push 1251
call SetConsoleCP
call SetConsoleOutputCP
pop ecx
mov [lcl_set], 1
;push lcl
;call [system]
; pop ecx
; mov [lcl_set], 1
;push cls
;call [printf]
; pop ecx
__set_locale_rest:
ret 0
section '.idata' import data readable
library kernel,'kernel32.dll',\
msvcrt,'msvcrt.dll'
import kernel,\
SetConsoleCP,'SetConsoleCP',\
SetConsoleOutputCP,'SetConsoleOutputCP',\
ExitProcess,'ExitProcess'
import msvcrt,\
printf,'printf'
It works almost perfectly, except that before exiting it waits for like a second for some reason. It outputs data almost instantly, yet it fails to shut down quickly. If the reason is using these libraries or not clearing the stack after calling ExitProcess (which obviously can't be done), then let me know and I will mostly gladly accept this answer, but I want to be 100% sure I'm doing everything correctly.
The reason for all of it was because kernel32 functions pop their parameters themselves on return. If I remove unnecessary pops it starts working fast again. Of course, the program still runs with damaged stack but it does a lot of damage control at the end. That's why it was slow, but still worked. For everyone facing this issue, make sure to be careful with the calling convention.
To debug the application and find the error I used OLLYDBG. It's free and it works. It helps you debug EXEs and DLLs, allowing to step one command at a time. Also it shows the memory, the stack and all of the registers and flags.
Using the stack I was able to find out that it gets corrupted.
Related
I am trying to print a string in assembly without having to store my data into a variable.
What works:
global _main
extern _printf
section .data:
message: db 'AAAA'
section .text
_main:
push message
call _printf
add esp, 4
ret
Now, what I want is to push AAAA directly to stack and call printf to print it without having to store it in message.
I spent good few hours with different methods trying to do it myself, but so far failed.
Tried:
Method #1:
push 41414141h
call _printf
Method #2:
mov esi, 41414141h
push esi
call _printf
Method #3:
mov esi, 41414141h
mov edi, 7325 ; '%s'
call _printf
; or storing 'AAAA' in EDI and storing '%s' in ESI
Method #4:
mov esi, 41414141h
mov edi, 7325 ; '%s'
push esi
push edi
call _printf
; or storing 'AAAA' in EDI and storing '%s' in ESI
Method #5:
mov esi, 41414141h
mov edi, 7325 ; '%s'
push esi
xor eax, eax
push eax ; just push a null byte to the stack
push edi
call _printf
; or storing 'AAAA' in EDI and storing '%s' in ESI
and many more that I don't even remember.
So, what is the proper way of printing a value stored in a register.
and if possible to answer below too, I would really appreciate it.
After investigating a bit on how does the first attempt works. I realized that, the the data or AAAA is stored in program's stack and then the address of the data is pushed to ESP.
enter image description here
Unfortunately, I don't how to push data to program's stack\ .data section or if that is even possible and how to push the address of that section to ESP.
I'm not used to using the _printf function, but I can show how you can do this with the syscall:
mov dword [esp-4], 'AAAA' ; This is the red-zone, try googling it
; The actual printing
mov eax, 4
mov ebx, 1
lea ecx, [esp-4]
mov edx, 4
int 80h
(This uses the Linux 32-bit syscalls by the way, not sure what the windows syscalls are)
Maybe try pushing [esp-4]?
[EDIT] Forgot to mention a major limitation of this (At least with the syscall, still not sure about _printf) that this can only print a max of 4 characters, no more.
[ANOTHER EDIT] As other commenters have pointed out, this method is possibly unsafe (check comments), so you may decide to avoid it.
I've spend lot of time trying to solve this problem and I don't understand, why it doesn't work. Problem's description is in comments below:
.386
.MODEL FLAT, STDCALL
OPTION CASEMAP:NONE
.NOLIST
.NOCREF
INCLUDE \masm32\include\windows.inc
.LIST
.CODE
DllEntry PROC hInstDLL:HINSTANCE, reason:DWORD, reserved1:DWORD
mov eax, TRUE
ret
DllEntry ENDP
caesarAsm proc string: DWORD, key: DWORD, stringLength : DWORD
mov esi, 1 ; I cannot use this register, mov esi, (anything) causes Crash:
; Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention
mov eax, string
ret
caesarAsm endp
END DllEntry
I searched "whole" Internet, I found that the problem is connected with stack, but no operation on stacks helped me to solve it.
I'm using Microsoft Visual Studio 2012
I assume the error does not occur in this function, rather, it is triggered elsewhere. The esi register is a callee-saved register. You must make sure its value is the same at function exit as it was at entry. You can use it in your function, but you must save and restore its value. Such as:
push esi
mov esi, 1
mov eax, string
pop esi
ret
This is all well documented. You may only use eax, ecx and edx without saving.
Side note: you are using high-level features of your assembler, you might want to check the actual generated code or refrain from using them until you are confident in what the result is going to be. Incidentally masm has a USES keyword which would do the save/restore for you.
I'm new to windows programming and started working on a text game a few months ago. I decided to rewrite the WM_PAINT section of my code, I normally had the entire client area continually redrawn but thought I'd try redrawing specific regions instead to reduce flicker. I noticed in one specific section of my code, InvalidateRect/UpdateWindow doesn't seem to want to work, but if I replace the 2 functions with RedrawWindow, it displays perfectly. Should there be an instance where InvalidateRect/UpdateWindow fails to work but RedrawWindow works fine in it's place?
Would there be any drawbacks to just replace all InvalidateRect/UpdateWindow calls in my code with RedrawWindow?
Thanks for an info!
.if uMsg==WM_PAINT
invoke BeginPaint,hWnd,ADDR ps
mov hdc,eax
.if (PAINT_DMGMSG>0) ;contains ->to a char's DMGMSG
invoke CreateFont,16,12,0,0,400,0,0,0,OEM_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,NULL
invoke SelectObject,hdc,eax
mov hfont,eax
invoke SetTextColor,hdc,COLOR_SNOWWHITE
mov esi,TS_MSG2
mov edi,TS_MSG1
mov ecx,len(TS_MSG2)
rep movsb
mov BYTE ptr [edi],0
mov esi,TS_MSG3
mov edi,TS_MSG2
mov ecx,len(TS_MSG3)
rep movsb
mov BYTE ptr [edi],0
mov esi,PAINT_DMGMSG
mov edi,TS_MSG3
mov ecx,len(esi)
rep movsb
mov BYTE ptr [edi],0
invoke TextOut,hdc,0,500,TS_MSG1,len(TS_MSG1)
invoke TextOut,hdc,0,518,TS_MSG2,len(TS_MSG2)
invoke TextOut,hdc,0,536,TS_MSG3,len(TS_MSG3)
mov PAINT_DMGMSG,0
.endif
invoke EndPaint,hWnd,ADDR ps
.elseif uMsg==WM_CHAR ;used to handle keyboard input
push wParam
pop char
.if(SDWORD ptr [ebx+OFFSET_ALLEGIANCE]<0)&&(DWORD ptr [ebx+OFFSET_STATUS]!=STAT_DEAD)
invoke Combat,[esi+12],ebx
mov ebx,[edi+4]
mov eax,[human.color]
mov [ebx+OFFSET_CHARCOLOR],eax
mov ebx,pChar
mov ebx,[ebx+OFFSET_MOBMEM]
.if (DWORD ptr [ebx+OFFSET_MOBMEM_DMGMSG]>0)
mov ebx,[ebx+OFFSET_MOBMEM_DMGMSG]
mov XYrc.left,0
mov XYrc.top,500
push wWin
pop XYrc.right
mov XYrc.bottom,560 ;+font height
mov PAINT_DMGMSG,ebx
; invoke InvalidateRect,hWnd,ADDR XYrc,TRUE
; invoke UpdateWindow,hWnd
invoke RedrawWindow,hWnd,ADDR XYrc,NULL,NULL ;<- WORKS FINE!
.endif
.endif
Assuming you use 0 as the last argument for the RedrawWindow() (as you do), there indeed is one important difference:
UpdateWindow() sends WM_PAINT immediately, before the function returns.
RedrawWindow() (unless flag RDW_UPDATENOW is used) just places WM_PAINT into the message queue so the painting actually happens later.
This can make difference, if you invalidate the rectangle, but change the window state then after. In case (1), the control is painted using the "old" data, but (2) "works".
If your issue is caused by this difference, you may try to use InvalidateRect() only (do not call UpdateWindow(), nor RedrawWindow(). The rect invalidation will cause then WM_PAINT will come when the queue has no other event in it. (Originally UpdateWindow() prevented that as the immediate WM_PAINT validates the window as a side effect of the painting).
I'm stepping through Structured Error Handling recovery code in Windows 7
(e.g, what happens after SEH handler is done and passes back "CONTINUE" code).
Here's a function which is called:
7783BD9F mov edi,edi
7783BDA1 push ebp
7783BDA2 mov ebp,esp
7783BDA4 push 1
7783BDA6 push dword ptr [ebp+0Ch]
7783BDA9 push dword ptr [ebp+8]
7783BDAC call 778692DF
7783BDB1 pop ebp
7783BDB2 ret 8
I'm used to the function prolog of "push ebp/mov ebp,esp". What's the purpose
of the "mov edi,edi"?
Raymond Chen (one of the Microsoft developers) has answered this exact question:
Why do Windows functions all begin with a pointless MOV EDI, EDI instruction?
And he links an even earlier reference:
Why does the compiler generate a MOV EDI, EDI instruction at the beginning of functions?
Basically, it leaves space for a jump instruction to be inserted during hot patching.
OK, I'm new to PC Assembler. I"m trying to write an program, but it won't stop looping. I'm guessing the ECX register is being modified? How can I fix this? Thanks.
DATA SECTION
;
KEEP DD 0 ;temporary place to keep things
;
CODE SECTION
;
START:
MOV ECX,12
TOPOFLOOP:
PUSH -11 ;STD_OUTPUT_HANDLE
CALL GetStdHandle ;get, in eax, handle to active screen buffer
PUSH 0,ADDR KEEP ;KEEP receives output from API
PUSH 5,'bruce' ;5=length of string
PUSH EAX ;handle to active screen buffer
CALL WriteFile
XOR EAX,EAX ;return eax=0 as preferred by Windows
LOOP TOPOFLOOP
ENDLABEL:
RET
In most x86 calling convention, including the stdcall convention used by Windows API functions, ECX is a caller-save register -- the called function is not required to make sure the value of the register is the same when it returns as when it was called. You have to save it somewhere safe in your own code.