flat assembler
Message board for the users of flat assembler.
Index
> Windows > keep console |
Author |
|
gunblade 12 Dec 2012, 10:48
Code: format PE Console entry start include 'win32a.inc' include 'api\kernel32.inc' inputHandle dd ? title db 'Derp derp',0 inputBuffer rb 256 hasRead dd 0 mustRead dd 1 start: stdcall [GetStdHandle], STD_INPUT_HANDLE mov [inputHandle], eax stdcall [ReadConsoleA], [inputHandle], inputBuffer, [mustRead], hasRead, NULL stdcall [ExitProcess], 0 data import library kernel,'KERNEL32.DLL' import kernel,\ ExitProcess, 'ExitProcess',\ GetStdHandle, 'GetStdHandle',\ SetConsoleTitleA, 'SetConsoleTitleA',\ ReadConsoleA,'ReadConsoleA',\ WriteConsoleA, 'WriteConsoleA' end data No need for the AllocConsole if you use PE Console (I believe PE without any parameters defaults to PE Console anyway (correct me if i'm wrong here - but for me, it was opening a console anyway even without the console setting to the PE format)). And yeah, 2 main issues - your mustRead was 0, should be at least 1. You were also passing the ADDRESS of inputHandle and mustRead, rather than the actual value - need to dereference those with the [] brackets. Something which might be an issue - this will only exit once you enter the Enter key.. not ANY key. This is because the console and those console commands work per-line.. it will let you enter as many characters as you want, and only return from the ReadConsole when a newline is encountered. |
|||
12 Dec 2012, 10:48 |
|
Jordi 12 Dec 2012, 15:13
Thank you for your response.
You where absolulty right. First there is no need to allocate the console in PE mode. And indeed I needed to dereference both the variables. According to the reference both variables have the LP prefix. If I am correct this means that they are Long Pointers. Is that why I needed to dereference them? If so this makes a lot clear. http://msdn.microsoft.com/en-us/library/windows/desktop/ms684958(v=vs.85).aspx Thank you for your help! |
|||
12 Dec 2012, 15:13 |
|
gunblade 12 Dec 2012, 15:25
Nah, its the other two variables..
inputHandle and mustRead are hConsoleInput and nNumberOfCharsRead respectively. These two are NOT lp*, and therefore these should be actual data/values. This is why you have to use [] brackets in order to pass the value at the address, rather than the address itself. The other two parameters are lp*, and hence expect an address, where the function can then store the data (as these other parameters are OUT parameters). The function will write its output data to the address you give it. In general, IN parameters tend to be data itself, whereas OUT will be addresses (as the function cannot directly modify the data that you pass it unless it knows where it is stored). Slightly off-topic: you should use sections in your file, as in: Code: format PE Console entry start include 'win32a.inc' include 'api\kernel32.inc' section '.data' data readable writeable inputHandle dd ? title db 'Derp derp',0 inputBuffer rb 256 hasRead dd 0 mustRead dd 1 section '.text' code readable executable start: stdcall [GetStdHandle], STD_INPUT_HANDLE mov [inputHandle], eax stdcall [ReadConsoleA], [inputHandle], inputBuffer, [mustRead], hasRead, NULL stdcall [ExitProcess], 0 section '.idata' import data readable library kernel,'KERNEL32.DLL' import kernel,\ ExitProcess, 'ExitProcess',\ GetStdHandle, 'GetStdHandle',\ SetConsoleTitleA, 'SetConsoleTitleA',\ ReadConsoleA,'ReadConsoleA',\ WriteConsoleA, 'WriteConsoleA' It's good practice to have a section for data which is writeable, and a seperate section for the code which isnt. Otherwise some antiviruses (if not windows itself) might complain at code writing data to the executable section. (kind of impressed it actually worked with no section - i deffinetly thought windows would have forbidden it - but aparently not. It might if the No-Execute feature had been enabled). |
|||
12 Dec 2012, 15:25 |
|
Jordi 12 Dec 2012, 16:49
I don't know if you have any C knowledge.
oke out parameters are like references in C. You pass the memory adress instead of the value. like this Code: void doSomething(int& a_Par1) { } and to dereference like in C you use this. You pass the value... Code: (*itr) |
|||
12 Dec 2012, 16:49 |
|
gunblade 13 Dec 2012, 09:23
Yeah, you have it right in C - but C behaves differently by default.
Say you had an unsigned int value - if you were to call a function by doing something(value), you'd be by default passing the actual "data" inside that variable, rather than an address to it. If you wanted to explicitely pass the address to it, you'd have to do something(&value) as you say. Whereas, in assembly, using the variable name actually uses the variable's address by default, so doing something like: Code: stdcall [something], value would actually be equivalent to the C of something(&value). You'd have to do: Code: stdcall [something], [value] to get the equivalent of something(value). Although this also depends on the "type" used in C.. because for example, doing: Code: unsigned char buffer[256]; will actually make the variable name buffer use the address by default (as its a reference to an array - you cant really pass the "value" as it could be of any length), so for that one - something(buffer) would be the equivalent of: Code: stdcall [something],buffer and something(*buffer) (which would be the same as something(buffer[0])) would by the equivalent of: Code: stdcall [something],[buffer] Hopefully that's not too unreadable There's a better explanation in section 1.2.3 of the fasm manual: http://flatassembler.net/docs.php?article=manual#1.2.3 |
|||
13 Dec 2012, 09:23 |
|
baldr 13 Dec 2012, 10:54
Actually following lines are equivalent:
Code: stdcall [something], args... invoke something, args... |
|||
13 Dec 2012, 10:54 |
|
gunblade 13 Dec 2012, 11:31
Yeah, I stuck to stdcall convension as it was what he used in his original code. Didnt want to add more confusion by switching it up
But you're right, invoke is neater.. if you're already using macros, might as well use the neater of the two. |
|||
13 Dec 2012, 11:31 |
|
Picnic 13 Dec 2012, 11:58
Jordi wrote: My goal is to startup the console, and keep it untill I enter a character. Hi Jordi, You may also use getch from msvcrt library. Below a script you might find helpful, notice the use of cinvoke here. Code: ;#include <stdio.h> ;#include <conio.h> ; ;void main(void) ;{ ; int ch, scan; ; ; do { ; ch = getch(); /* 1st getch() gets ASCII code */ ; printf("Character is %d\n", ch); ; if (ch == 0x00 || ch == 0XE0) { /* if extended key */ ; scan = getch(); /* 2nd getch() gets "scan code" */ ; printf("\tExtended character: scan is %d\n", scan); ; } ; } while (ch != 27); /* exit loop on ESC */ ;} format pe console entry main include "win32ax.inc" section ".data" data readable writeable CR equ 13,10 chr dd 0 scan dd 0 section ".code" code readable executable main: .repeat cinvoke getch mov [chr], eax cinvoke printf, <"Character is %d",CR>, [chr] .if ( [chr] = 0x00 | [chr] = 0xE0 ) cinvoke getch mov [scan], eax cinvoke printf, <0x09,"Extended character: scan is %d",CR>, [scan] .endif .until ( [chr] = 27 ) invoke ExitProcess, 0 section ".idata" import data readable writeable library kernel32,"KERNEL32.DLL",\ msvcrt, "MSVCRT.DLL" include "include/api/kernel32.inc" import msvcrt,\ getch, "_getch",\ printf, "printf" |
|||
13 Dec 2012, 11:58 |
|
Jordi 13 Dec 2012, 12:13
Thank you very much. This makes a lot clear. It is somethimes diffcult to do things that look quite simple in C or C++. Xd
|
|||
13 Dec 2012, 12:13 |
|
typedef 13 Dec 2012, 14:39
Jordi wrote:
This is C++ not C. |
|||
13 Dec 2012, 14:39 |
|
Jordi 14 Dec 2012, 12:21
Hi i have got two more questions that are a little bit difficult to tackle.
First if I would like to print a double precision floating point it is quite easy but if i would like to print a double precision floating point it seems really difficult. According to the documentation you could push a single precision floating point on the stack using Code:
push dword 12.21
But when i print it it does show some weird output Code: format PE Console entry main ;include basic 32-bit code include 'win32a.inc' include 'api\kernel32.inc' ;define nessesary variable section '.data' data readable writeable inputHandle dd ? title db 'derp derp',0 inputBuffer rb 256 hasRead dd 0 mustRead dd 1 integerFormat db '%d',0 floatFormat db '%2.2f',0 section '.text' code readable executable main: stdcall [GetStdHandle], STD_INPUT_HANDLE mov [inputHandle], eax push dword 12.12 stdcall [printf], floatFormat, dword [esp] ; stdcall [printf], integerFormat, [var5] stdcall [ReadConsoleA], [inputHandle], inputBuffer, [mustRead], hasRead, NULL stdcall [ExitProcess], 0 section '.idata' import data readable writeable library kernel,'KERNEL32.DLL',\ msvcrt,'msvcrt.dll' import kernel,\ ExitProcess, 'ExitProcess',\ GetStdHandle, 'GetStdHandle',\ SetConsoleTitleA, 'SetConsoleTitleA',\ ReadConsoleA,'ReadConsoleA' import msvcrt,\ printf,'printf' and my second question i also could find no answer on it nor on the forum, nor in the documentation. You could push memory, register or imediate value on the stack. If i chouse the latter. How do i pop it from the stack. You could only pop memory and registers from the stack... Could someone explain me this? Thank you very much. |
|||
14 Dec 2012, 12:21 |
|
Jordi 14 Dec 2012, 12:49
I found a answer on the last question.
If i push a 4 byte value on to the stack i could pop it of the stack to use pop with an operand. It does not mean that i must just that operand further. However I still could not understand why I still could not print a signle precision floating point. Could someone help me with that? |
|||
14 Dec 2012, 12:49 |
|
Jordi 14 Dec 2012, 14:31
oew I suceeded.
What I did was that i converted the dword to a qword float so i was able to print it with printf. |
|||
14 Dec 2012, 14:31 |
|
typedef 14 Dec 2012, 15:09
Your call to printf is wrong.
Code: push dword 12.12 stdcall [printf], floatFormat, dword [esp] use this Code: push dword 12.12 push floatFormat call [printf] add esp, 8 ; OR cinvoke printf, floatFormat, 12.12 |
|||
14 Dec 2012, 15:09 |
|
AsmGuru62 14 Dec 2012, 16:22
Or you can store the 8 bytes directly from FPU into stack:
Code: push 12.34 fld dword [esp] push eax fstp qword [esp] but the 12.34 being FLOAT first and then DOUBLE will lose some precision. |
|||
14 Dec 2012, 16:22 |
|
baldr 15 Dec 2012, 09:01
AsmGuru62,
With all due respect, why does anyone need FPU (for a constant case) if Win32AX.Inc already have pushd macro? Code: pushd double 12.34 ; push 0x4028AE14 ; push 0x7AE147AE |
|||
15 Dec 2012, 09:01 |
|
Jordi 22 Dec 2012, 14:01
Aha okidokie thank you for the help.
I was wondering when you create a function at the end jou need to use a ret instruction to restore the stack. I've created a function and I call the ret function, that is what i supposed to do according to the manual. However when I call the ret instruction my console crashes. It pops up and than it dissapears. Am I doing something wrong. Sorry for al those questions but I really would like to understand fasm. here is my code. Code: format PE entry start ;include basic 32-bit code include 'win32ax.inc' ;define nessesary variable inputHandle dd ? title db 'Derp derp',0 inputBuffer rb 256 hasRead dd 0 mustRead dd 1 integerFormat db '%d',0 floatFormat db '%2.2f',0 start: stdcall [GetStdHandle], STD_INPUT_HANDLE mov [inputHandle], eax call WProc proc WProc mov edx, 12 ret endp stdcall [printf], integerFormat, edx stdcall [ReadConsoleA], [inputHandle], inputBuffer, [mustRead], hasRead, NULL stdcall [ExitProcess], 0 data import library kernel,'KERNEL32.DLL',\ msvcrt,'msvcrt.dll' import kernel,\ ExitProcess, 'ExitProcess',\ GetStdHandle, 'GetStdHandle',\ SetConsoleTitleA, 'SetConsoleTitleA',\ ReadConsoleA,'ReadConsoleA' import msvcrt,\ printf,'printf' end data Thanks in advance. |
|||
22 Dec 2012, 14:01 |
|
baldr 22 Dec 2012, 15:11
Jordi,
You've placed WProc() inside main function, this is wrong. Actually code of WProc() is executed twice: once because of call WProc, again because after return from call code path lies along it. Second time ret from this function returns to OS. Move it below stdcall [ExitProcess], 0 and everything'll be OK. |
|||
22 Dec 2012, 15:11 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.