News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

My third 64 bit console app...

Started by felipe, May 24, 2018, 02:24:32 PM

Previous topic - Next topic

felipe

I'm doing it well? (At least the program works correctly, after writting to the console press enter and the program finish...):


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This file was created by Felipe at 2018-05-24.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

option casemap:none
include \masm32\include64\win64.inc
include \masm32\include64\kernel32.inc
includelib  \masm32\lib64\kernel32.lib

.data
inbuff      byte    256 dup(" ")

.data?
chrsread    dword   ?

.code
start   proc
        sub     rsp,40      ; Shadow space + stack alignment.

        call    AllocConsole

        mov     rcx,STD_INPUT_HANDLE
        call    GetStdHandle

        add     rsp,40      ; Restores the stack.

        push    NULL        ; Reserved.

        sub     rsp,40      ; Shadow space + stack alignment.

        mov     rcx,rax     ; stdin.   
        lea     rdx,inbuff
        mov     r8,256      ; Chars to read.
        lea     r9,chrsread
        call    ReadConsole

        add     rsp,8

        call    FreeConsole

        xor     rcx,rcx
        call    ExitProcess

        add     rsp,40      ; Restores the stack.
start   endp
        end


.exe attached.

aw27

Does not crash this time but is wrong.
Try like this:


option casemap:none
include \masm32\include64\win64.inc
include \masm32\include64\kernel32.inc
includelib  \masm32\lib64\kernel32.lib

.data
inbuff      byte    256 dup(" ")

.data?
chrsread    dword   ?

.code
start   proc
        sub     rsp,40      ; Shadow space + stack alignment + STACK VARIABLES SPACE FOR THE WHOLE PROCEDURE.

        call    AllocConsole

        mov     rcx,STD_INPUT_HANDLE
        call    GetStdHandle

        ;add     rsp,40      ; WRONG

        ;push    NULL        ; Reserved. DON't DO PUSHES

        ;sub     rsp,40      ; Shadow space + stack alignment. NO

  mov qword ptr [RSP+32], NULL ; LIKE THIS
        mov     rcx,rax     ; stdin.   
        lea     rdx,inbuff
        mov     r8,256      ; Chars to read.
        lea     r9,chrsread
        call    ReadConsole

        ;add     rsp,8 ; WRONG

        call    FreeConsole

        xor     rcx,rcx
        call    ExitProcess

        ;add     rsp,40      ; WRONG. YOU WILL NOT COME HERE
start   endp
        end


mineiro

Hello felipe, you're on the right path, keep walking.
At start of your procedure (sub rsp, ??) just ignore for a while that value and keep coding. After your procedure is done, get the function that have more parameters inside your procedure and based on that you have a value to be inserted at sub rsp, ??. Well, it's a memory eater as you can see because you alloc all memory need. Next challenge can be local variables inside your procedure.
One thing to remember are odd and even parameters to stack alignment. Other thing are leaf functions (the one that don't call others), they can be seen as different way.
I'd rather be this ambulant metamorphosis than to have that old opinion about everything

felipe


option casemap:none
include \masm32\include64\win64.inc
include \masm32\include64\kernel32.inc
includelib  \masm32\lib64\kernel32.lib

.data
inbuff      byte    256 dup(" ")

.data?
chrsread    dword   ?

.code
start   proc
        sub     rsp,40      ; Shadow space + stack alignment + STACK VARIABLES SPACE FOR THE WHOLE PROCEDURE. Ok i think i understand             
                                  ;    this. The extra parameters go "above" the shadow space.
        call    AllocConsole

        mov     rcx,STD_INPUT_HANDLE
        call    GetStdHandle

        ;add     rsp,40      ; WRONG   I did this based in "the caller is responsible of cleaning the stack". So i thought this must be done until
                                    ;   call to a procedure that needs more stack space. Seems like in this simple program case windows clean all for us 
                                    ;     when the process is done?
        ;push    NULL        ; Reserved. DON't DO PUSHES. So we can only do pushes when we are using a stack frame?

        ;sub     rsp,40      ; Shadow space + stack alignment. NO

  mov qword ptr [RSP+32], NULL ; LIKE THIS.
        mov     rcx,rax     ; stdin.   
        lea     rdx,inbuff
        mov     r8,256      ; Chars to read.
        lea     r9,chrsread
        call    ReadConsole

        ;add     rsp,8 ; WRONG

        call    FreeConsole

        xor     rcx,rcx
        call    ExitProcess

        ;add     rsp,40      ; WRONG. YOU WILL NOT COME HERE. I know, but i thought it would be good coding practice (not too efficient 
                                    ;   really).
start   endp
        end


Thanks, i have a lot to learn with this (i mean 64 bits programming), so i will not expect all the answers for my questions right now. But thank you very much to both anyway.  :icon14: :icon14:

aw27

Quote
;I did this based in "the caller is responsible of cleaning the stack". So i thought this must be done until
;   call to a procedure that needs more stack space. Seems like in this simple program case windows clean all for us 
;     when the process is done?
You can do but you should not do, if a procedure calls 1000 times other procedures you will spend a lot of time reserving and clearing stack. So, all should be done in the beginning of the procedure reserving space for the procedure that will use the most stack and keeping in mind that all procedures will be called with the stack aligned.

Quote
So we can only do pushes when we are using a stack frame?
The problem with the pushes is that they change the alignment.
So, if you align in the beginning of the procedure why are going to misalign?

All right, these things take time to understand.  :t


felipe


mineiro

When program is loaded on memory rsp have a value ???????8h, we need subtract 1*8 bytes to align to a multiple of 16, so rsp == ???????0, now we can 'call' an external function (non leaf).
Next is necessary reserve space to shadow space (rcx,rdx,r8,r9), 4*8.
Next is to a function that use more parameters inside your procedure (ReadConsole) that need 1 argument on stack == 1*8.
Sub rsp, 1*8+4*8, so 1(parameter)+4(shadow) == 5, stack aligned (odd + odd rsp == even), it's ok. If even, you can do your own way or just add 8 to that value.
Again, at start of your procedure after you alloc memory to shadow space you can store rcx,rdx,... into that memory variables, not sure if this helps a diagnosis when program have a fault but we ignore that (Exception handler?).

When you push that value you're going from even (???????0) to odd (???????8), any values are ok to a leaf function, but function that call other functions gets in trouble.

edited --- odd and even :)
I'd rather be this ambulant metamorphosis than to have that old opinion about everything

hutch--

 :biggrin:

Now you know why I bothered to write an adjustable stackframe macro for procedure entry and exit. With Win32 using ML.EXE a procedure was a simple construction, MASM automatically produced the entry and exit to a procedure which you could override if you did not want a stack frame but ML64 does not do that as the 64 bit calling convention is a lot more complicated. With procedures over 4 arguments you need a stack frame if you are not immediately aware of the stack location for passed arguments and with a stack frame you can directly allocate LOCAL variables to do sensible things like preserve and restore registers.

The point with the stackframe macro was that it ensured correct alignment without having to try and twiddle the stack manually.

To call a procedure I wrote the macro "procedure_call" and use a number of wrappers to call it ("invoke" and a few others) that puts the arguments in the right place, handles the copying of the first 4 args into shadow space then loads the rest of the arguments (if there is more than 4) into the correct stack locations.

Once you have the two macros working together the stackframe procedure can be used in a simple and reliable manner with the arguments in the right place and as many LOCAL variables as you need.

Mikl__

#8
Hi, felipe!
I have decided to look by means of a value debugger which are returned by the GetStdHandle function. To the surprise I have found these values are constants.
|Windows
|10 x64
|Windows
|Seven x64
|Windows
|XP 32-bits
|Windows
|    98
|  UNIX
|and DOS
hInput|50h=101.0000b|   3 =00.11b|  3|   8 =0.1.0.00b|0=00b - standart input device
hOutput|54h=101.0100b|   7 =01.11b|  7|0Ch=0.1.1.00b|1=01b - standart output device
hError|58h=101.1000b|0Bh=10.11b|0Bh|10h=1.0.0.00b|2=10b - standart error device
Maybe it is worth using the fixed values, but not to cause every time the GetStdHandle function?

felipe

Quote from: Mikl__ on May 25, 2018, 03:48:52 PM
Maybe it is worth using the fixed values, but not to cause every time the GetStdHandle function?

Sounds ok, but maybe a little risky?  :idea:

Quote from: hutch-- on May 25, 2018, 01:05:24 PM
Now you know why I bothered to write an adjustable stackframe macro for procedure entry and exit.

I know is complicated now, even with a lot of help it will take me some time to handle this... :biggrin:

@mineiro: I liked your explanations. But i'm a little confused with how you are using the terms even and odd, there. I don't know how would be possible you get the rsp with an odd value, if is always decremented by 8 and it starts with a multiple of 8. Maybe you are using this terms to denote 16 byte aligned and not 16 byte aligned?  :idea:

Thanks to all.  :icon14:

mineiro

Quote from: felipe on May 26, 2018, 04:15:23 AM
Maybe you are using this terms to denote 16 byte aligned and not 16 byte aligned?  :idea:
Yes sir, you take the point.
I'd rather be this ambulant metamorphosis than to have that old opinion about everything

daydreamer

Quote from: felipe on May 26, 2018, 04:15:23 AM
Quote from: Mikl__ on May 25, 2018, 03:48:52 PM
Maybe it is worth using the fixed values, but not to cause every time the GetStdHandle function?

Sounds ok, but maybe a little risky?  :idea:

Quote from: hutch-- on May 25, 2018, 01:05:24 PM
Now you know why I bothered to write an adjustable stackframe macro for procedure entry and exit.

I know is complicated now, even with a lot of help it will take me some time to handle this... :biggrin:

@mineiro: I liked your explanations. But i'm a little confused with how you are using the terms even and odd, there. I don't know how would be possible you get the rsp with an odd value, if is always decremented by 8 and it starts with a multiple of 8. Maybe you are using this terms to denote 16 byte aligned and not 16 byte aligned?  :idea:

Thanks to all.  :icon14:
nice attempt,but as all assembly demos usually exit with esc key I had to force it to Close,first run,before I read you checked for enter key instead
just thinking,after you make 9 attempts,but fails attempt 8 and attempt 9, you maybe succeded with Seven of Nine  :P  :lol:
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

felipe

Quote from: mineiro on May 26, 2018, 05:35:24 AM
Yes sir, you take the point.

That's great mineiro, you are a good teacher.  :biggrin: Thanks.  :icon14:

Mikl__

Quote from: felipeSounds ok, but maybe a little risky?
Hi, felipe!
While you are studying and you still have nothing to lose. You run the risk, but at the same time gain experience and knowledge...

felipe