flat assembler
Message board for the users of flat assembler.
Index
> Windows > bug in calling convention Goto page 1, 2 Next |
Author |
|
revolution 11 Sep 2021, 15:32
Before you can alter RSP manually with "AND SPL,..." you need to save the original RSP somewhere.
Usually RBP is used to keep the original RSP value, so that later you can recover. Code: mov rbp, rsp ; save original rsp and spl, ... ; ... mov rsp, rbp ; recover original rsp ret |
|||
11 Sep 2021, 15:32 |
|
macomics 11 Sep 2021, 16:10
And it's nothing that the WriteFile function has 5 parameters, not 4. And the 5 parameter in your case is passed as rsp-lpOverlapped. Operations with the console go immediately and do not use postponed I/O, but with files it's just the opposite.
|
|||
11 Sep 2021, 16:10 |
|
pabloreda 11 Sep 2021, 16:11
I use rbp for other stack and the adress of stack in ret position is Ok, but be 0, is like window clear this position in stack.
with 2 parameters this work ok, but all pararameters are passed with registers. Code: ; sys-SetConsoleMode add rbp,8 mov [rbp],rax mov rax,qword[w6] ; SYS2 PUSH RSP PUSH qword [RSP] ADD RSP,8 AND SPL,0F0h sub RSP,$20 mov rdx,[rbp] mov rcx,[rbp-1*8] call rax add RSP,$20 sub rbp,8*2 POP RSP ; DROP mov rax,[rbp] sub rbp,8 |
|||
11 Sep 2021, 16:11 |
|
revolution 11 Sep 2021, 16:15
You can't use "POP RSP" because the value of RSP has changed, so the value poped will come from a different addres, and now your code will crash.
Remember that PUSH/POP use RSP for the address pointer. So changing RSP changes the stack pointer, and your code crashes. |
|||
11 Sep 2021, 16:15 |
|
pabloreda 11 Sep 2021, 16:30
@macominc,
It is not a specific call, it is only the structure for when the call has 5 parameters, in the interpreter that works correctly this is the code (gcc output) Code: loc_4032DE: ; jumptable 0000000000402846 case 124 mov rax, [r13+0] mov rdx, [r13-18h] sub r13, 28h ; '(' mov rcx, [r13+8] mov r9, [r13+20h] mov r8, [r13+18h] mov [rsp+0D8h-0B8h], rax call r11 mov r11, rax jmp loc_402859 ; jumptable 0000000000402846 case 130 you can see, not need adjust stack for align or shadow stack because is a bigloop without calls but this is made by GCC, when compile I use call then unalign stack then need realign when comunicate whit the OS. @revolution this is a macro for align the stack I use from this forum, I think Locodelassembly is the author, I test in the prior compiler and work ok |
|||
11 Sep 2021, 16:30 |
|
revolution 11 Sep 2021, 16:37
Your instruction "AND SPL,0F0h" adjusts the stack pointer.
|
|||
11 Sep 2021, 16:37 |
|
macomics 11 Sep 2021, 16:43
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile wrote: Considerations for working with synchronous file handles: Code: typedef struct _OVERLAPPED { ULONG_PTR Internal; // rewrite rsp ULONG_PTR InternalHigh; union { struct { DWORD Offset; DWORD OffsetHigh; } DUMMYSTRUCTNAME; PVOID Pointer; } DUMMYUNIONNAME; HANDLE hEvent; } OVERLAPPED, *LPOVERLAPPED; pabloreda wrote:
|
|||
11 Sep 2021, 16:43 |
|
pabloreda 11 Sep 2021, 17:19
ok, then 5 parameter is place bad in the shadow stack!!, thanks macomix !!
|
|||
11 Sep 2021, 17:19 |
|
bitRAKE 11 Sep 2021, 23:03
It's a cute trick to restore RSP:
Code: PUSH RSP PUSH qword [RSP] ; another copy ADD RSP,8 ; could be superfluous AND SPL,0F0h ; adjunst 16bytes align |
|||
11 Sep 2021, 23:03 |
|
pabloreda 12 Sep 2021, 01:27
from here https://board.flatassembler.net/topic.php?t=11133
crazy things do now the code...I need research more |
|||
12 Sep 2021, 01:27 |
|
revolution 12 Sep 2021, 01:53
bitRAKE wrote: It's a cute trick to restore RSP:[code]PUSH RSP It's much simpler to just follow the standard and then everything works fine. The standard itself, the fastcall for x64, is a bit silly IMO, but it does work. There isn't any need to make it worse with storing the stack pointer on the stack. If you already know where the stored stack pointer is on the stack then that means you already know where the stack is pointing, so no need to "restore" it, you had it all along. |
|||
12 Sep 2021, 01:53 |
|
bitRAKE 12 Sep 2021, 02:01
I use ENTER/LEAVE almost everywhere because I like how the VIRTUAL block documents the stack frame. I don't use INVOKE because it doesn't track needed stack depth (maximum parameter count). I've tried a lot of different automatic methods and settled on manually defining the frame.
Code: MainWindow.InitCloseButton: ;HWND (stack) virtual at RBP-.FRAME rq 4 repeat 13-4,k:5 .P.k dq ? end repeat .tbar dq ?,? .FRAME := $-$$ rq 2 ; RBP,ret .hWnd dq ? end virtual enter .FRAME,0 Code: SetWindowBlur: ; HWND (on stack) virtual at RBP-.FRAME rq 4 .hMod dq ? ; HINSTANCE .FRAME := $-$$ dq ? ; RBP dq ? ; ret .hWnd dq ? end virtual enter .FRAME,0 LoadLibraryA <ANSI 'user32'> xchg rcx,rax jrcxz .fail mov [.hMod],rcx ; Might be broken in the future due to this undocumented API ; https://www.google.com/search?q=SetWindowCompositionAttribute GetProcAddress rcx,<ANSI 'SetWindowCompositionAttribute'> test rax,rax jz @F call rax,[.hWnd],ADDR .data ; WINCOMPATTRDATA @@: FreeLibrary [.hMod] .fail: leave retn 8 This is just the model that works well for me. Edit: I use the stack for dynamic storage frequently and being able to cleanup with LEAVE is convenient as well. More complex frames I add ASSERTs to insure I don't inadvertently mess up an alignment, but it's all well documented in the frame. Sections of a large frame can be redefined/repurposed - eliminating the need for changes in RSP/RBP. How would that look without ENTER/LEAVE - almost the same in this case: Code: SetWindowBlur: ; HWND (on stack) virtual at RSP rq 4 .hMod dq ? ; HINSTANCE dq ? .FRAME := $-$$ dq ? ; ret .hWnd dq ? end virtual sub rsp,.FRAME LoadLibraryA <ANSI 'user32'> xchg rcx,rax jrcxz .fail mov [.hMod],rcx GetProcAddress rcx,<ANSI 'SetWindowCompositionAttribute'> test rax,rax jz @F call rax,[.hWnd],ADDR .data ; WINCOMPATTRDATA @@: FreeLibrary [.hMod] .fail: add rsp,.FRAME retn 8 _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup Last edited by bitRAKE on 19 Sep 2021, 15:52; edited 2 times in total |
|||
12 Sep 2021, 02:01 |
|
macomics 12 Sep 2021, 04:27
revolution wrote: It's much simpler to just follow the standard and then everything works fine. The standard itself, the fastcall for x64, is a bit silly IMO, but it does work. There isn't any need to make it worse with storing the stack pointer on the stack. If you already know where the stored stack pointer is on the stack then that means you already know where the stack is pointing, so no need to "restore" it, you had it all along. Code: mov rsp, [rsp+32] ; instead of add rsp, $20 / pop rsp |
|||
12 Sep 2021, 04:27 |
|
revolution 12 Sep 2021, 07:26
You can't use "pop rsp" when the rsp value used to push was a different value than to pop. You get a corrupted stack.
Code: push rsp ; rsp before = 0x1000, value after = 0x0ff8 and spl, 0xf0 ; rsp before = 0x0ff8, value after = 0x0ff0 ; some code push something ; rsp before = 0x0ff0, value after = 0x0fe8 pop somthing ; rsp before = 0x0fe8, value after = 0x0ff0 ; some more code pop rsp ; rsp before = 0x0ff0, value after = unknown!! |
|||
12 Sep 2021, 07:26 |
|
pabloreda 12 Sep 2021, 12:29
thank'you all guys
The only comunication with the SO is using a LOADLIB, and GETPROC, then all the call are using this adress get in runtime. I not have parameters and local var in stack (RSP) then the calls inside the program are only with address, this two thing go in other stack (is a forth) I need somthing like this Code: invoke rax,qword[rbp],qword[rbp-1*8],qword[rbp-2*8],qword[rbp-3*8],qword[rbp-4*8] any recomentation for doing this? I'm workin in https://github.com/phreda4/r3/tree/main/asm code.asm is the code r3fasm.exe is the exe |
|||
12 Sep 2021, 12:29 |
|
macomics 12 Sep 2021, 12:49
revolution wrote: You can't use "pop rsp" when the rsp value used to push was a different value than to pop. You get a corrupted stack. Code: push rsp ; rsp before = 0x1000, value after = 0x0ff8, [rsp] = 0x1000 push qword [rsp] ; rsp before = 0x0ff8, value after = 0x0ff0, [rsp] = 0x1000, [rsp+8] too add rsp, 8 ; rsp before = 0x0ff0, value after = 0x0ff8, [rsp-8] = 0x1000, [rsp] = 0x1000 and spl, 0xf0 ; rsp before = 0x0ff8, value after = 0x0ff0, [rsp] = 0x1000 ; some code push something ; rsp before = 0x0ff0, value after = 0x0fe8 pop somthing ; rsp before = 0x0fe8, value after = 0x0ff0 ; some more code pop rsp ; rsp before = 0x0ff0, value after = 0x1000 |
|||
12 Sep 2021, 12:49 |
|
bitRAKE 12 Sep 2021, 22:37
pabloreda wrote: I need somthing like this Weird: github is interpreting the ASM file as a single line on my end. Actually, looking at the code - your quote is incorrect - the parameters are in the correct order on the stack. Code: invoke rax,qword[rbp-4*8],qword[rbp-3*8],qword[rbp-2*8],qword[rbp-1*8],qword[rbp] The ideal solution is not to copy parameters around. Code: mov rcx,[rbp+8*0] mov rdx,[rbp+8*1] mov r8,[rbp+8*2] mov r9,[rbp+8*3] xchg rsp,rbp call rax xchg rsp,rbp add rbp,params*8 _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
12 Sep 2021, 22:37 |
|
pabloreda 12 Sep 2021, 23:13
rbp is not in the same STACK, I have 2 stack, one with RSP, the normal one, for return of call and in other place with rbp like pointer, this is the key part of any Forth lenguage
|
|||
12 Sep 2021, 23:13 |
|
bitRAKE 13 Sep 2021, 01:28
Of course, I understand that. Just because it's separate doesn't mean it can't be swapped out for external calls. This is why it should be a downward moving stack - especially for 32-bit - which would only need:
Code: xchg esp,ebp call eax xchg esp,ebp _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
13 Sep 2021, 01:28 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.