1

I know from MS_Document ,X64 Calling Convention, Caller must Allocates some space for Callee.

but i wrote several codes with calling functions without allocating any shadow space but i did not see any error.

here it is for example [works without any error in Visual studio 2022 and disabled whole program optimization]

includelib msvcrt.lib
includelib legacy_stdio_definitions.lib

extern _CRT_INIT: proc     
extern printf: proc
extern ExitProcess: proc

.data
     msg db "hello world!", 13, 10, 0

.code
main proc 
  call _CRT_INIT       
  lea rcx,msg
  call printf
  call ExitProcess
main endp
end
Mohammad
  • 17
  • 5
  • 3
    You were lucky. Just because it seems to work in this case, doesn't mean it will always work. Note you do not use anything from the stack so if `printf` uses the shadow space it will only overwrite things you don't care about (since you don't even need the return address). You also misalign the stack, lucky on that account too. – Jester Jan 09 '23 at 20:49
  • @jester what about this one ? https://pastebin.com/VERs7wRx How lucky can a person be? :) – Mohammad Jan 09 '23 at 20:56
  • 1
    That does at least use the return address. Remember that the shadow space is available for the callee to use, but it is not required to. If the implementation of the functions you are calling does not, then you will see no ill effects. You could write an example with your own code that does use the shadow space if you want to see code break. – Jester Jan 09 '23 at 21:00
  • 2
    @Jester is correct (on both being lucky with the shadow space and the stack alignment). Try to modify the program to print 4 integers out using printf. Change the msg to `msg db "hello world!%d%d%d, %d", 13, 10, 0`. The 5th parameter (integer 4) has to be pushed on the stack. Without shadow space see what happens when you do `lea rcx,msg` `mov edx, 1` `mov r8d, 2` `mov r9d, 3` `push 4` `call printf` . That should print out the wrong number for the last value. If you add a `sub rsp, 32` just before the `call printf` to allocate the shadow space it probably works. – Michael Petch Jan 09 '23 at 21:13
  • @M.Petch Works Like a charm without any error again Shot:https://1drv.ms/u/s!ArAzfF5MuP3yiGP_t2fNeYWFB5eW?e=5epK31 – Mohammad Jan 09 '23 at 21:18
  • 1
    No error but it should not work because it should look for the 5th argument in the wrong place. It should not print the `4`. – Jester Jan 09 '23 at 21:19
  • Did you look at the last value printed, was it the value 4? or something else. – Michael Petch Jan 09 '23 at 21:20
  • oh sorry i figured out now yes 4 is missed – Mohammad Jan 09 '23 at 21:23
  • 1
    Tnx Both of you – Mohammad Jan 09 '23 at 21:24
  • Now if you put `sub rsp, 32` right after `push 4` it probably prints out 4. – Michael Petch Jan 09 '23 at 21:24
  • @M.Petch yes exactly – Mohammad Jan 09 '23 at 21:26
  • [Segmentation Fault while calling Printf](https://stackoverflow.com/q/39613511) is an example of breakage if you did rely on `main`'s return value after letting printf step on it (as part of its shadow space). – Peter Cordes Jan 10 '23 at 08:38
  • Deviating from the official calling convention should only be done when calling a function that you (or someone you know) wrote specifically for a different calling convention. For example, it is entirely doable for someone to create an x64 calling convention that doesn't specify the 32 byte space for argument spilling and use that for their own assembler functions. One limitation that cannot be escaped is that rules for what must be available at any potential point of system interrupt or CPU exception must be as the OS requires. For example on MS Windows, any address < rsp is bad – jb_dk Jun 22 '23 at 02:11

0 Answers0