.386 ; 32-битный режим
.model flat, stdcall ; компиляция в exe-файл с возможностью вызова API
option casemap :none ; неразличение прописных и строчных символов
; содержит значения констант
include C:\masm32\include\windows.inc ; STD_INPUT_HANDLE,
; STD_OUTPUT_HANDLE
include \masm32\include\winmm.inc
include <\masm32\include\kernel32.inc>
include <\masm32\include\user32.inc>
includelib <\masm32\lib\kernel32.lib>
includelib <\masm32\lib\user32.lib>
includelib c:\masm32\lib\winmm.lib
.const
MEMSIZE equ 65535
.data ; сегмент данных
hfile_write dd ?
hfile_read dd ?
buff_file db 0
file_read db "file_read.txt",0
file_write db "file_write.txt",0
file_read_size dd ? ;размер файла
size_file_read dd ? ;количество считанных байт
ByteWritten dd ?
hConsoleInput DWORD ? ; переменные для хранения хэндлов ввода и вывода,
hConsoleOutput DWORD ? ; названия этих переменных могут быть другими
; буфер 1 байт (со значением 0)
Buffer byte 1 dup (0) ; для вода с клавиатуры 1 символа,
; название буфера может быть другим
NumberOfCharsRead DWORD ? ; переменные для записи числа фактически
NumberOfCharsWritten DWORD ? ; введенных и выведенных символов,
; названия этих переменных могут быть другими
hMemory HANDLE ?
pMemory DWORD ?
msg1 byte "Задача выполненна успешно!" ; строковая переменная
; строковая переменная
msg2 byte "Нажмите Enter, чтобы выйти...", 0 ; заканчивается нулем,
; так как она будет передана
; API-функции CharToOem
msg1310 byte 13, 10 ; перевод строки
ERROR_CreateFile byte "ERROR_CreateFile",0
ERROR_GetFileSize byte "ERROR_GetFileSize",0
ERROR_VirtualAlloc byte "ERROR_VirtualAlloc",0
ERROR_ReadFile byte "ERROR_ReadFile",0
ERROR_WriteFile byte "ERROR_WriteFile",0
IDTime dword ?
.code ; сегмент кода
mytime proc hWnd, uMsg, idEvent, dwTime: DWORD ;hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD;
pushad
mov ecx,file_read_size
mov esi,pMemory
loop1:
movzx eax,byte ptr [esi]
mov eax,'f'
mov byte ptr [esi],al
;mov dword ptr [esi],eax
loop2:
inc esi
loop loop1
popad
ret
mytime endp
start:
invoke CreateFile, ADDR file_write,
GENERIC_WRITE or GENERIC_READ,
FILE_SHARE_WRITE or FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
;CMP EAX,-1
;JE _ERROR_CreateFile
mov hfile_write, eax
invoke CreateFile, ADDR file_read, ;открываем файл для чтения для получения дискриптора файла
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_READONLY,
NULL
;CMP EAX,-1
;JE _ERROR_CreateFile
mov hfile_read, eax
invoke GetFileSize, hfile_read, NULL ;получаем размер файла
;CMP EAX,0
;JE _ERROR_GetFileSize
mov file_read_size,eax
;mov ecx,eax
invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,MEMSIZE
mov hMemory,eax ;функция возвращает хэндл на запрошенный блок памяти
invoke GlobalLock,hMemory
mov pMemory,eax ;возвращает указатель на блок памяти
;mov esi,eax
invoke ReadFile, hfile_read, ;считываем данные с файла
pMemory, ;Адрес буфера
file_read_size, ;MEMSIZE-1, ;Размер буфера или сколько байтов нужно прочитать
ADDR size_file_read, ; Адрес переменной, в которую записывается реальное количество прочитанных данных
NULL
;CMP EAX,0
;JE _ERROR_ReadFile
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
invoke SetTimer, NULL,NULL, 1000, ADDR mytime
mov IDTime,eax
invoke KillTimer,NULL, [IDTime]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
invoke WriteFile, hfile_write,
pMemory, ; Указатель на буфер, содержащий данные, которые будут записаны в файл
size_file_read, ; Число байтов, которые будут записаны в файл
ADDR size_file_read,;ADDR ByteWritten, ;Указатель на переменную, которая получает число записанных байтов
NULL
;CMP EAX,0
;JE _ERROR_WriteFile
invoke CloseHandle, hfile_read
invoke CloseHandle, hfile_write
invoke GlobalUnlock,pMemory
invoke GlobalFree,hMemory
invoke AllocConsole ; запрашиваем у Windows консоль
invoke GetStdHandle, STD_INPUT_HANDLE ; получаем хэндл консоли для ввода
mov hConsoleInput, EAX ; записываем хэндл в переменную
invoke GetStdHandle, STD_OUTPUT_HANDLE ; получаем хэндл консоли для вывода
mov hConsoleOutput, EAX ; записываем хэндл в переменную
invoke WriteConsoleA, ; переводим строку в консоли
hConsoleOutput, ; хэндл вывода
ADDR msg1310, ; адрес строки msg1310
SIZEOF msg1310, ; размер строки msg1310
ADDR NumberOfCharsWritten, ; сюда функция запишет число символов
0 ; lpReserved передаем, как ноль
invoke CharToOem, ADDR msg1, ADDR msg1
invoke WriteConsoleA, ; пишем " Hello, World!"
hConsoleOutput,
ADDR msg1,
SIZEOF msg1,
ADDR NumberOfCharsWritten,
0
invoke WriteConsoleA, ; переводим строку
hConsoleOutput,
ADDR msg1310,
SIZEOF msg1310,
ADDR NumberOfCharsWritten,
0
;invoke CharToOem, ADDR msg2, ADDR msg2 ; перекодируем Win1251 -> DOS
invoke WriteConsoleA, ; пишем " Нажмите Enter, чтобы выйти..."
hConsoleOutput,
ADDR msg2,
(SIZEOF msg2) - 1, ; уменьшаем размер строки msg2 на 1 (из-за нуля)
ADDR NumberOfCharsWritten,
0
invoke ReadConsoleA, ; ожидаем ввода в консоль
hConsoleInput, ; хэндл ввода
ADDR Buffer, ; адрес буфера
1, ; вводим 1 символ
ADDR NumberOfCharsRead, ; сюда функция запишет число символов
0 ; lpReserved передаем, как ноль
invoke ExitProcess, 0 ; сообщаем системе, что программа окончена
end start ; завершает сегмент кода
Wow, reading Russian is a bit hard, not as Spanish, the most beautiful and easy language in the world, or... yes, English if there's nothing else :redface:
hello ikudesnik,
I'm not satisfied with SetTime either! For a better way to measure time, use RDTSC; see \masm32\macros\timers.asm for an example. Not sure if that's what you're looking for?
- you kill SetTimer, so how should it work?
- SetTimer requires a Windows loop, i.e. a GUI, not a console
.386; 32-bit mode
.model flat, stdcall; compile in exe-file of the API call with the possibility
option casemap: none; lack of distinction between uppercase and lowercase characters
; It provides constant values
include \ masm32 \ include \ windows.inc; STD_INPUT_HANDLE,
; STD_OUTPUT_HANDLE
include \ masm32 \ include \ winmm.inc
include <\ masm32 \ include \ kernel32.inc>
include <\ masm32 \ include \ user32.inc>
includelib <\ masm32 \ lib \ kernel32.lib>
includelib <\ masm32 \ lib \ user32.lib>
includelib \ masm32 \ lib \ winmm.lib
.const
MEMSIZE equ 65535
.data; data segment
hfile_write dd?
hfile_read dd?
buff_file db 0
file_read db "file_read.txt", 0
file_write db "file_write.txt", 0
file_read_size dd? ;file size
size_file_read dd? , the number of bytes read
ByteWritten dd?
hConsoleInput DWORD? ; variables to hold the handles input and output,
hConsoleOutput DWORD? ; the names of these variables may be different
; 1 byte buffer (with value 0)
1 Buffer byte dup (0); for water Keyboard symbol 1,
; the name of the buffer may be different
NumberOfCharsRead DWORD? ; to record the number of variables actually
NumberOfCharsWritten DWORD? ; input and output symbols,
; the names of these variables may be different
hMemory HANDLE?
pMemory DWORD?
msg1 byte "mission accomplished successfully!" ; string variable
; string variable
msg2 byte "Press Enter, to come out ...", 0; It ends with a zero,
; as it will be transferred
; API-function CharToOem
msg1310 byte 13, 10; line translation
ERROR_CreateFile byte "ERROR_CreateFile", 0
ERROR_GetFileSize byte "ERROR_GetFileSize", 0
ERROR_VirtualAlloc byte "ERROR_VirtualAlloc", 0
ERROR_ReadFile byte "ERROR_ReadFile", 0
ERROR_WriteFile byte "ERROR_WriteFile", 0
IDTime dword?
.code; code segment
mytime proc hWnd, uMsg, idEvent, dwTime: DWORD; hWnd: DWORD, uMsg: DWORD, wParam: DWORD, lParam: DWORD;
pushad
mov ecx, file_read_size
mov esi, pMemory
loop1:
movzx eax, byte ptr [esi]
mov eax, 'f'
mov byte ptr [esi], al
; mov dword ptr [esi], eax
loop2:
inc esi
loop loop1
popad
ret
mytime endp
start:
invoke CreateFile, ADDR file_write,
GENERIC_WRITE or GENERIC_READ,
FILE_SHARE_WRITE or FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
; CMP EAX, -1
; JE _ERROR_CreateFile
mov hfile_write, eax
invoke CreateFile, ADDR file_read,; open the file to read for diskriptora file
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_READONLY,
NULL
; CMP EAX, -1
; JE _ERROR_CreateFile
mov hfile_read, eax
invoke GetFileSize, hfile_read, NULL; get the file size
; CMP EAX, 0
; JE _ERROR_GetFileSize
mov file_read_size, eax
; mov ecx, eax
invoke GlobalAlloc, GMEM_MOVEABLE or GMEM_ZEROINIT, MEMSIZE
mov hMemory, eax; function returns a handle to the requested memory block
invoke GlobalLock, hMemory
mov pMemory, eax; returns a pointer to the memory block
; mov esi, eax
invoke ReadFile, hfile_read,; read data from the file
pMemory,; address buffer
file_read_size,; MEMSIZE-1, buffer size, or how many bytes you need to read
ADDR size_file_read,; Address of the variable which is written the actual number of read data
NULL
; CMP EAX, 0
; JE _ERROR_ReadFile
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
invoke SetTimer, NULL, NULL, 1000, ADDR mytime
mov IDTime, eax
invoke KillTimer, NULL, [IDTime]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
invoke WriteFile, hfile_write,
pMemory,; Pointer to the buffer containing the data to be written to a file
size_file_read,; The number of bytes that will be written to a file
ADDR size_file_read,; ADDR ByteWritten,; Pointer to a variable that receives the number of bytes written
NULL
; CMP EAX, 0
; JE _ERROR_WriteFile
invoke CloseHandle, hfile_read
invoke CloseHandle, hfile_write
invoke GlobalUnlock, pMemory
invoke GlobalFree, hMemory
invoke AllocConsole; queries the Windows console
invoke GetStdHandle, STD_INPUT_HANDLE; We get the handle console input
mov hConsoleInput, EAX; write handle variable
invoke GetStdHandle, STD_OUTPUT_HANDLE; We obtain a handle to the console output
mov hConsoleOutput, EAX; write handle variable
invoke WriteConsoleA,; newline console
hConsoleOutput,; handle output
ADDR msg1310,; address line msg1310
SIZEOF msg1310,; line size msg1310
ADDR NumberOfCharsWritten,; here the function will record the number of characters
0; lpReserved pass as zero
invoke CharToOem, ADDR msg1, ADDR msg1
invoke WriteConsoleA,; write "Hello, World!"
hConsoleOutput,
ADDR msg1,
SIZEOF msg1,
ADDR NumberOfCharsWritten,
0
invoke WriteConsoleA,; newline
hConsoleOutput,
ADDR msg1310,
SIZEOF msg1310,
ADDR NumberOfCharsWritten,
0
; invoke CharToOem, ADDR msg2, ADDR msg2; recoding Win1251 -> DOS
invoke WriteConsoleA,; write "Press Enter, to come out ..."
hConsoleOutput,
ADDR msg2,
(SIZEOF msg2) - 1; reduce the size of line msg2 1 (due to zero)
ADDR NumberOfCharsWritten,
0
invoke ReadConsoleA,; I look forward to the console
hConsoleInput,; handle input
ADDR Buffer,; buffer address
1, ; enter 1 character
ADDR NumberOfCharsRead,; here the function will record the number of characters
0; lpReserved pass as zero
invoke ExitProcess, 0; We tell the system that the program is over
end start; completes code segment
even if in Russian, tell us what you want and what is not working :t
we can use google translate, and get a pretty good idea
How to organize a loop: every two seconds to process one character in the console?
you can use Sleep
mov ebx,10
.repeat
lea eax,[ebx-1]
print str$(eax),32
INVOKE Sleep,2000 ;time in mS
dec ebx
.until ZERO?
print chr$(13,10)
It is necessary to use the API function with timer :(
i guess what you want to do is use SetTimer and KillTimer
generally, we use it to send WM_TIMER messages
but, that's not the only way to use it
https://msdn.microsoft.com/en-us/library/windows/desktop/ms644906%28v=vs.85%29.aspx (https://msdn.microsoft.com/en-us/library/windows/desktop/ms644906%28v=vs.85%29.aspx)
another way to use it is with a callback function
when the time elapses, a PROC is called
notice that the timer function is passed 4 dword arguments
https://msdn.microsoft.com/en-us/library/windows/desktop/ms644907%28v=vs.85%29.aspx (https://msdn.microsoft.com/en-us/library/windows/desktop/ms644907%28v=vs.85%29.aspx)
i can make an example, but not tonight - it's bed time :P
Can I use timesetevent?
Can you give an example of my problem?
Maybe this may help. Fasm syntax, sorry, don't have masm at hand now. Regards.
The file. Isn't possible to attach a file on editing a post?
I'm probably a fool-I can not understand :icon_eek:
it is necessary to call a function
invoke timeSetEvent,20000,0,addr mytime,TIME_ONESHOT,TIME_CALLBACK_FUNCTION
mov IDTime,eax
invoke timeKillEvent, IDTime
After 20 seconds, the procedure "mytime" should work
but it does not work :(
.386 ; 32-битный режим
.model flat, stdcall ; компиляция в exe-файл с возможностью вызова API
option casemap :none ; неразличение прописных и строчных символов
; содержит значения констант
include C:\masm32\include\windows.inc ; STD_INPUT_HANDLE,
; STD_OUTPUT_HANDLE
include \masm32\include\winmm.inc
include <\masm32\include\kernel32.inc>
include <\masm32\include\user32.inc>
includelib <\masm32\lib\kernel32.lib>
includelib <\masm32\lib\user32.lib>
includelib c:\masm32\lib\winmm.lib
.const
MEMSIZE equ 65535
.data ; сегмент данных
hfile_write dd ?
hfile_read dd ?
buff_file db 0
file_read db "file_read.txt",0
file_write db "file_write.txt",0
file_read_size dd ? ;размер файла
size_file_read dd ? ;количество считанных байт
ByteWritten dd ?
hConsoleInput DWORD ? ; переменные для хранения хэндлов ввода и вывода,
hConsoleOutput DWORD ? ; названия этих переменных могут быть другими
; буфер 1 байт (со значением 0)
Buffer byte 1 dup (0) ; для вода с клавиатуры 1 символа,
; название буфера может быть другим
NumberOfCharsRead DWORD ? ; переменные для записи числа фактически
NumberOfCharsWritten DWORD ? ; введенных и выведенных символов,
; названия этих переменных могут быть другими
hMemory HANDLE ?
pMemory DWORD ?
msg1 byte "Задача выполненна успешно!" ; строковая переменная
; строковая переменная
msg2 byte "Нажмите Enter, чтобы выйти...", 0 ; заканчивается нулем,
; так как она будет передана
; API-функции CharToOem
msg1310 byte 13, 10 ; перевод строки
ERROR_CreateFile byte "ERROR_CreateFile",0
ERROR_GetFileSize byte "ERROR_GetFileSize",0
ERROR_VirtualAlloc byte "ERROR_VirtualAlloc",0
ERROR_ReadFile byte "ERROR_ReadFile",0
ERROR_WriteFile byte "ERROR_WriteFile",0
IDTime dword ?
.code ; сегмент кода
mytime proc ;hWnd, uMsg, idEvent, dwTime: DWORD ;hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD;
pushad
mov ecx,file_read_size
mov esi,pMemory
loop1:
movzx eax,byte ptr [esi]
mov eax,'f'
mov byte ptr [esi],al
;mov dword ptr [esi],eax
loop2:
inc esi
loop loop1
popad
ret
invoke timeKillEvent, IDTime
mytime endp
start:
invoke CreateFile, ADDR file_write,
GENERIC_WRITE or GENERIC_READ,
FILE_SHARE_WRITE or FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
;CMP EAX,-1
;JE _ERROR_CreateFile
mov hfile_write, eax
invoke CreateFile, ADDR file_read, ;открываем файл для чтения для получения дискриптора файла
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_READONLY,
NULL
;CMP EAX,-1
;JE _ERROR_CreateFile
mov hfile_read, eax
invoke GetFileSize, hfile_read, NULL ;получаем размер файла
;CMP EAX,0
;JE _ERROR_GetFileSize
mov file_read_size,eax
;mov ecx,eax
invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,MEMSIZE
mov hMemory,eax ;функция возвращает хэндл на запрошенный блок памяти
invoke GlobalLock,hMemory
mov pMemory,eax ;возвращает указатель на блок памяти
;mov esi,eax
invoke ReadFile, hfile_read, ;считываем данные с файла
pMemory, ;Адрес буфера
file_read_size, ;MEMSIZE-1, ;Размер буфера или сколько байтов нужно прочитать
ADDR size_file_read, ; Адрес переменной, в которую записывается реальное количество прочитанных данных
NULL
;CMP EAX,0
;JE _ERROR_ReadFile
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
invoke timeSetEvent,20000,0,addr mytime,TIME_ONESHOT,TIME_CALLBACK_FUNCTION ;http://rusapi.narod.ru/timeSetEvent.htm
mov IDTime,eax
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
invoke WriteFile, hfile_write,
pMemory, ; Указатель на буфер, содержащий данные, которые будут записаны в файл
size_file_read, ; Число байтов, которые будут записаны в файл
ADDR size_file_read,;ADDR ByteWritten, ;Указатель на переменную, которая получает число записанных байтов
NULL
;CMP EAX,0
;JE _ERROR_WriteFile
invoke CloseHandle, hfile_read
invoke CloseHandle, hfile_write
invoke GlobalUnlock,pMemory
invoke GlobalFree,hMemory
invoke AllocConsole ; запрашиваем у Windows консоль
invoke GetStdHandle, STD_INPUT_HANDLE ; получаем хэндл консоли для ввода
mov hConsoleInput, EAX ; записываем хэндл в переменную
invoke GetStdHandle, STD_OUTPUT_HANDLE ; получаем хэндл консоли для вывода
mov hConsoleOutput, EAX ; записываем хэндл в переменную
invoke WriteConsoleA, ; переводим строку в консоли
hConsoleOutput, ; хэндл вывода
ADDR msg1310, ; адрес строки msg1310
SIZEOF msg1310, ; размер строки msg1310
ADDR NumberOfCharsWritten, ; сюда функция запишет число символов
0 ; lpReserved передаем, как ноль
invoke CharToOem, ADDR msg1, ADDR msg1
invoke WriteConsoleA, ; пишем " Hello, World!"
hConsoleOutput,
ADDR msg1,
SIZEOF msg1,
ADDR NumberOfCharsWritten,
0
invoke WriteConsoleA, ; переводим строку
hConsoleOutput,
ADDR msg1310,
SIZEOF msg1310,
ADDR NumberOfCharsWritten,
0
;invoke CharToOem, ADDR msg2, ADDR msg2 ; перекодируем Win1251 -> DOS
invoke WriteConsoleA, ; пишем " Нажмите Enter, чтобы выйти..."
hConsoleOutput,
ADDR msg2,
(SIZEOF msg2) - 1, ; уменьшаем размер строки msg2 на 1 (из-за нуля)
ADDR NumberOfCharsWritten,
0
invoke ReadConsoleA, ; ожидаем ввода в консоль
hConsoleInput, ; хэндл ввода
ADDR Buffer, ; адрес буфера
1, ; вводим 1 символ
ADDR NumberOfCharsRead, ; сюда функция запишет число символов
0 ; lpReserved передаем, как ноль
invoke ExitProcess, 0 ; сообщаем системе, что программа окончена
end start ; завершает сегмент кода
It is important to understand that SetTimer needs a message loop to work. In general, a console app with no WndProc doesn't have a message loop. But even a simple MessageBox will create one:
include \masm32\include\masm32rt.inc
.code
CbTimer proc hwnd:DWORD, uMsg:DWORD, PMidEvent:DWORD, dwTime:DWORD
print "*"
ret
CbTimer endp
start:
invoke SetTimer, 0, 123, 50, CbTimer
inkey "hit any key, then Escape"
.Repeat
print "#"
invoke Sleep, 100 ; this will NOT allow the timer callback to execute
invoke GetKeyState, VK_ESCAPE
test ah, ah
.Until Sign?
MsgBox 0, "Congrats", "SetTimer in console app:", MB_OK
exit
end start
An alternative is to create a program with WndProc etc but to build it as console app. SetTimer will work just fine, and you can hide the main window if you don't want it.
Quote from: ikudesnik on September 04, 2015, 06:11:48 PM
I'm probably a fool-I can not understand :icon_eek:
it is necessary to call a function
invoke timeSetEvent,20000,0,addr mytime,TIME_ONESHOT,TIME_CALLBACK_FUNCTION
mov IDTime,eax
invoke timeKillEvent, IDTime
After 20 seconds, the procedure "mytime" should work
but it does not work :(
- Actually I haven't used these functions, but achieve the same thing within the Window loop. But I think I see two problems,
- you're killing the event as soon as you set it up, long before it fires, that's no good.
- more important you usually want to use a Windows, not console, program to do this. The Windows program stays resident (active) as it processes its message loop, until the user exits, so it will still be there 20 seconds later. But this console program will run in a few milliseconds and exit, and that's the end of it. When the timer event fires, it's not going to go out to disk and reload your program to find your "mytime" proc! instead, the timer event is cancelled when your prog exits. This only works in a Windows prog; or else a console prog with some sort of loop to keep it running for 20 seconds.
- Easiest apprach, just wait until dedndave drags his lazy *** out of bed, and posts an example - that will show you how it works
[edit] wrote this b4 seeing jj2007's previous post, which makes this one more-or-less redundant (except the advice about dedndave is still applicable)
Quote from: rrr314159 on September 04, 2015, 07:37:55 PMjust wait until dedndave drags his lazy *** out of bed, and posts an example
It's not just the ***, the whole person is lazy - 7928 posts only 8)
The challenge is strictly in the console using api functions.
Settime is not suitable for the console?
timeSetEvent is the multi-media version of SetTimer
Jochen - i think you can use them in console apps
1) i don't think it needs a message loop to work - if you use a callback
2) console apps do have a message loop, completely hidden from the normal console app
the console window is a GUI app :biggrin:
we will find out soon, because my lazy ass is up - lol
Quote from: dedndave on September 04, 2015, 10:47:40 PMJochen - i think you can use them in console apps
1) i don't think it needs a message loop to work - if you use a callback
2) console apps do have a message loop, completely hidden from the normal console app
the console window is a GUI app :biggrin:
Try the snippet in reply #14. (http://masm32.com/board/index.php?topic=4561.msg48917#msg48917). Add this line before MsgBox:
print chr$(13,10,"Callback kicks in", 13, 10)
But your point 2 is indeed an interesting idea ::)
Unfortunately, there are some special rules for consoles (see Raymond Chen (http://blogs.msdn.com/b/oldnewthing/archive/2007/12/31/6909007.aspx)). Such as: Access to its message loop denied :(
ok, here is one using the multi-media functions...
by the way, i noticed a sentance in the docs....
Quoteoops - wrong document - lol
i guess the timer uses a queue all its' own :P
https://msdn.microsoft.com/en-us/library/dd757634%28v=vs.85%29.aspx (https://msdn.microsoft.com/en-us/library/dd757634%28v=vs.85%29.aspx)
oh - it was in the other one :lol:
Looks convincing - it works even if you insert an inkey into the sleep loop :t
ok - SetTimer does not work without a message loop, as JJ mentioned before
i figured it could use hwndConsole (from GetConsoleWindow) - that does not work
QuoteAn application can process WM_TIMER messages by including a WM_TIMER case statement in the window
procedure or by specifying a TimerProc callback function when creating the timer. When you specify a TimerProc
callback function, the default window procedure calls the callback function when it processes WM_TIMER.
Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of
processing WM_TIMER.
sorry about that :biggrin:
What I have normally seen in this type of situation is make a normal UI window and start it off screen, -1000,-1000 used to do the trick. Set your timer in the UI window and trigger whatever you need from there.
Quote from: hutch-- on September 05, 2015, 12:22:57 AM
What I have normally seen in this type of situation is make a normal UI window and start it off screen, -1000,-1000 used to do the trick. Set your timer in the UI window and trigger whatever you need from there.
Started as an extra thread, I suppose? The window could be hidden, too.
i find that, if you set the X, Y, width, and height all to 0, it's hard to see :biggrin:
Give an example please?
Reply #20 has a working console example using timeSetEvent
attached here is a simple small window program, but i thought you wanted a console app
;create the window
INVOKE CreateWindowEx,edi,offset szClassName,offset szAppName,
WS_OVERLAPPEDWINDOW or WS_VISIBLE or WS_CLIPCHILDREN,
CW_USEDEFAULT,SW_SHOWNORMAL,MAIN_WIDTH,MAIN_HEIGHT,edi,edi,ebx,edi
if you want it to be invisible, change that line to...
;create the window
INVOKE CreateWindowEx,edi,offset szClassName,offset szAppName,
WS_OVERLAPPEDWINDOW or WS_CLIPCHILDREN,
edi,edi,edi,edi,edi,edi,ebx,edi
What's wrong, it does not start?
.386 ; 32-битный режим
.model flat, stdcall ; компиляция в exe-файл с возможностью вызова API
option casemap :none ; неразличение прописных и строчных символов
; содержит значения констант
include C:\masm32\include\windows.inc ; STD_INPUT_HANDLE,
; STD_OUTPUT_HANDLE
include \masm32\include\winmm.inc
include <\masm32\include\kernel32.inc>
include <\masm32\include\user32.inc>
includelib <\masm32\lib\kernel32.lib>
includelib <\masm32\lib\user32.lib>
includelib c:\masm32\lib\winmm.lib
MSGSTRUCT STRUC
MSHWND DD ? ;идентификатор окна, получающего сообщение
MSMESSAGE DD ? ;идентификатор сообщения
MSWPARAM DD ? ;дополнительная информация о сообщении
MSLPARAM DD ? ;дополнительная информация о сообщении
MSTIME DD ? ;время посылки сообщения
MSPT DD ? ;положение курсора, во время посылки сообщения
MSGSTRUCT ENDS
.const
MEMSIZE equ 65535
.data ; сегмент данных
hfile_write dd ?
hfile_read dd ?
buff_file db 0
file_read db "file_read.txt",0
file_write db "file_write.txt",0
file_read_size dd ? ;размер файла
size_file_read dd ? ;количество считанных байт
ByteWritten dd ?
hConsoleInput DWORD ? ; переменные для хранения хэндлов ввода и вывода,
hConsoleOutput DWORD ? ; названия этих переменных могут быть другими
; буфер 1 байт (со значением 0)
Buffer byte 1 dup (0) ; для вода с клавиатуры 1 символа,
; название буфера может быть другим
NumberOfCharsRead DWORD ? ; переменные для записи числа фактически
NumberOfCharsWritten DWORD ? ; введенных и выведенных символов,
; названия этих переменных могут быть другими
hMemory HANDLE ?
pMemory DWORD ?
msg1 byte "Задача выполненна успешно!" ; строковая переменная
; строковая переменная
msg2 byte "Нажмите Enter, чтобы выйти...", 0 ; заканчивается нулем,
; так как она будет передана
; API-функции CharToOem
msg1310 byte 13, 10 ; перевод строки
ERROR_CreateFile byte "ERROR_CreateFile",0
ERROR_GetFileSize byte "ERROR_GetFileSize",0
ERROR_VirtualAlloc byte "ERROR_VirtualAlloc",0
ERROR_ReadFile byte "ERROR_ReadFile",0
ERROR_WriteFile byte "ERROR_WriteFile",0
IDTime dword ?
lpMsg MSGSTRUCT <?>
.code ; сегмент кода
mytime proc ;hWnd:DWORD, uMsg:DWORD, idEvent:DWORD, dwTime:DWORD
pushad
mov ecx,file_read_size
mov esi,pMemory
loop1:
movzx eax,byte ptr [esi]
mov eax,'f'
mov byte ptr [esi],al
;mov dword ptr [esi],eax
loop2:
inc esi
loop loop1
popad
ret
mytime endp
start:
invoke CreateFile, ADDR file_write,
GENERIC_WRITE or GENERIC_READ,
FILE_SHARE_WRITE or FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
;CMP EAX,-1
;JE _ERROR_CreateFile
mov hfile_write, eax
invoke CreateFile, ADDR file_read, ;открываем файл для чтения для получения дискриптора файла
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_READONLY,
NULL
;CMP EAX,-1
;JE _ERROR_CreateFile
mov hfile_read, eax
invoke GetFileSize, hfile_read, NULL ;получаем размер файла
;CMP EAX,0
;JE _ERROR_GetFileSize
mov file_read_size,eax
;mov ecx,eax
invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,MEMSIZE
mov hMemory,eax ;функция возвращает хэндл на запрошенный блок памяти
invoke GlobalLock,hMemory
mov pMemory,eax ;возвращает указатель на блок памяти
;mov esi,eax
invoke ReadFile, hfile_read, ;считываем данные с файла
pMemory, ;Адрес буфера
file_read_size, ;MEMSIZE-1, ;Размер буфера или сколько байтов нужно прочитать
ADDR size_file_read, ; Адрес переменной, в которую записывается реальное количество прочитанных данных
NULL
;CMP EAX,0
;JE _ERROR_ReadFile
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;установить таймер
invoke SetTimer, NULL, NULL, 1000, ADDR mytime
mov IDTime,eax
@@Repeat:
invoke GetMessage, addr lpMsg, NULL, 0, 0
cmp eax,0
je @@Exit
invoke TranslateMessage, addr lpMsg
invoke DispatchMessage, addr lpMsg
;cmp lpMsg.message, WM_CHAR
;jz @@Exit
jmp @@Repeat
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
invoke WriteFile, hfile_write,
pMemory, ; Указатель на буфер, содержащий данные, которые будут записаны в файл
size_file_read, ; Число байтов, которые будут записаны в файл
ADDR size_file_read,;ADDR ByteWritten, ;Указатель на переменную, которая получает число записанных байтов
NULL
;CMP EAX,0
;JE _ERROR_WriteFile
invoke CloseHandle, hfile_read
invoke CloseHandle, hfile_write
invoke GlobalUnlock,pMemory
invoke GlobalFree,hMemory
invoke AllocConsole ; запрашиваем у Windows консоль
invoke GetStdHandle, STD_INPUT_HANDLE ; получаем хэндл консоли для ввода
mov hConsoleInput, EAX ; записываем хэндл в переменную
invoke GetStdHandle, STD_OUTPUT_HANDLE ; получаем хэндл консоли для вывода
mov hConsoleOutput, EAX ; записываем хэндл в переменную
invoke WriteConsoleA, ; переводим строку в консоли
hConsoleOutput, ; хэндл вывода
ADDR msg1310, ; адрес строки msg1310
SIZEOF msg1310, ; размер строки msg1310
ADDR NumberOfCharsWritten, ; сюда функция запишет число символов
0 ; lpReserved передаем, как ноль
invoke CharToOem, ADDR msg1, ADDR msg1
invoke WriteConsoleA, ; пишем " Hello, World!"
hConsoleOutput,
ADDR msg1,
SIZEOF msg1,
ADDR NumberOfCharsWritten,
0
invoke WriteConsoleA, ; переводим строку
hConsoleOutput,
ADDR msg1310,
SIZEOF msg1310,
ADDR NumberOfCharsWritten,
0
;invoke CharToOem, ADDR msg2, ADDR msg2 ; перекодируем Win1251 -> DOS
invoke WriteConsoleA, ; пишем " Нажмите Enter, чтобы выйти..."
hConsoleOutput,
ADDR msg2,
(SIZEOF msg2) - 1, ; уменьшаем размер строки msg2 на 1 (из-за нуля)
ADDR NumberOfCharsWritten,
0
invoke ReadConsoleA, ; ожидаем ввода в консоль
hConsoleInput, ; хэндл ввода
ADDR Buffer, ; адрес буфера
1, ; вводим 1 символ
ADDR NumberOfCharsRead, ; сюда функция запишет число символов
0 ; lpReserved передаем, как ноль
@@Exit:
invoke timeKillEvent, IDTime
invoke ExitProcess, 0 ; сообщаем системе, что программа окончена
end start ; завершает сегмент кода
приложение окно необходимо использовать SetTimer
Эта программа создает и окно GUI и окно консоли.
Окно графического интерфейса используется для таймера, и окно консоли для отображения используется.
Окно GUI не видно.
With another API function and C#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
//https://msdn.microsoft.com/en-us/library/windows/desktop/ms687003(v=vs.85).aspx
VOID CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired)
{
printf("#");
}
int main(void)
{
HANDLE hQueue,hTimer;
if ((hQueue = CreateTimerQueue()) != 0) {
CreateTimerQueueTimer(&hTimer,hQueue,(WAITORTIMERCALLBACK)TimerRoutine,0,1000,1000,0);
while (getchar() != 10);
DeleteTimerQueueTimer(hQueue,hTimer,INVALID_HANDLE_VALUE);
DeleteTimerQueue(hQueue);
}
return 0;
}
Quote from: TWell on September 05, 2015, 03:59:13 PM
With another API function and C#define WIN32_LEAN_AND_MEAN
Works like a charm BUT:
warning #2030: '=' used in a conditional expression:
if (hQueue = CreateTimerQueue()) {
Is that intentional? When using == it stops working ::)
Fixed(hQueue = CreateTimerQueue()) != 0
OK, so you are assigning and testing for errors at the same time.
Here is the assembler version:
include \masm32\include\masm32rt.inc
.code
TimerRoutine proc lParam, TimerOrWaitFired
print "#"
ret
TimerRoutine endp
start:
print "Timer in console:", 13, 10
invoke CreateTimerQueue
push eax ; save hTimerQueue
push eax ; create slot for hTimer
mov ecx, esp
invoke CreateTimerQueueTimer, ecx, eax, TimerRoutine, 0, 127, 127, 0
push eax ; timer-queue timer
.Repeat
getkey
push eax
print esp
pop eax
.Until al==VK_ESCAPE
print "*", 13, 10
pop eax ; timer-queue timer
pop ecx ; hTimer
invoke DeleteTimerQueueTimer, eax, ecx, INVALID_HANDLE_VALUE
call DeleteTimerQueue ; invoke DeleteTimerQueue, [esp]
print LastError$()
invoke Sleep, 2000
exit
end start
Thanks, i forgot thatDeleteTimerQueueTimer(hQueue,hTimer,INVALID_HANDLE_VALUE);
MSDN (https://msdn.microsoft.com/en-us/library/windows/desktop/ms682569%28v=vs.85%29.aspx):
QuoteCompletionEvent [in, optional]
If this parameter is INVALID_HANDLE_VALUE, the function waits for any running timer callback functions to complete before returning.
If this parameter is NULL, the function marks the timer for deletion and returns immediately.
Programmers at work in Redmond:
Quote"Ok, let's take -1 for 'complete before returning'"
"No, you can't call it -1, give it a proper name"
"Oh well, -1... let me think ... INVALID_HANDLE_VALUE?"
;)