0

I tried to run the simple code below:

extrn MessageBoxA: PROC
extrn ExitProcess: PROC

.data
titles db 'Win64', 0
msg db 'Hello World!', 0

.code

main proc
    sub rsp, 28h      ; 32 byte for 4 arguments, 8 byte for 'call' it self
    mov rcx, 0        ; hWnd = HWND_DESKTOP
    lea rdx, msg      ; LPCSTR lpText
    lea r8,  titles   ; LPCSTR lpCaption
    mov r9d, 0        ; uType = MB_OK
    call MessageBoxA
    mov ecx, eax
    add rsp, 28h
main endp
End

When I move it to a function the code no longer works:

extrn MessageBoxA: PROC
extrn ExitProcess: PROC

.data
titles db 'Win64', 0
msg db 'Hello World!', 0

msgbox_ready:
sub rsp, 28h      ; 32 byte for 4 arguments, 8 byte for 'call' it self
mov rcx, 0        ; hWnd = HWND_DESKTOP
lea rdx, msg      ; LPCSTR lpText
lea r8,  titles   ; LPCSTR lpCaption
mov r9d, 0        ; uType = MB_OK
call MessageBoxA
mov ecx, eax
add rsp, 28h

.code
main proc
  call msgbox_ready
main endp
End

If I move the contents of msgbox_ready to function main it seems to be okay. What is the issue? Can it be because its outside of .code section?

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
Ali Sepehri-Amin
  • 493
  • 1
  • 6
  • 18
  • `.data` gets linked into a page with read+write but not exec permission, so yes it faults if you call into if, even if you just had an empty function that just runs a `ret` instruction. – Peter Cordes Sep 05 '20 at 12:22
  • @PeterCordes I moved into `.code` but didnt work aswell – Ali Sepehri-Amin Sep 05 '20 at 12:24
  • @MichaelPetch: I removed the winapi tag. The question happens to use WinAPI as its example, but it's not about that. It would be the same question if it was a simple `foo: ret` in the data section, so people looking for stuff about winapi won't want to see this question or its answer, IMO. – Peter Cordes Sep 05 '20 at 12:24
  • @Ali: then that would be a completely different question, about debugging your code. (And a bad one, because it's missing a [mcve] and description of the problem.) Use a debugger to see where it faults, if it crashes, and/or describe what doesn't work. Obviously you're missing `ret` instructions after your functions, so it can't exit cleanly. – Peter Cordes Sep 05 '20 at 12:27
  • @MichaelPetch: Tags should be chosen to help future readers. As experts, we should choose tags based on what's *actually* relevant. If the OP had originally tagged it winapi that would be one thing; I might even leave that tag there, but they didn't and there's IMO no reason it should be. (Although it seems this might be an XY problem, where they actually want help getting a Hello World example working, even though they started with some experiment of moving code into the .data section.) – Peter Cordes Sep 05 '20 at 12:32
  • @PeterCordes I edited my question and ITS NOT ABOUT WinAPI. – Ali Sepehri-Amin Sep 05 '20 at 12:42
  • @MichaelPetch: The tag-usage guidelines for `[assembly]` state that question should be tagged with an ISA. Also, not all ISAs allow read-without-exec permission. x86-64 does. If you want to remove x86-64 and just leave [masm], that would work I guess. – Peter Cordes Sep 05 '20 at 13:05
  • 1
    Ali, what has compelled you to move the code into the data section to begin with? What was it you thought would be solved with that? Seems like you may have been trying to solve one problem by inadvertently creating another. – Michael Petch Sep 05 '20 at 13:21
  • @MichaelPetch: Yeah agreed, the OP keeps distorting it into a WinAPI question, that's one reason I didn't remove the tag again. Their self-answer is answering about what happens after moving the function back into `.code`. The actual question has a much simpler answer, which is that code-fetch from `.data` will #PF page fault right away. The fact that the code has other bugs is necessary to deal with if you want to answer beyond that to the point of actually making a working program out of it. Then the [calling-convention] tag could apply, or sure [winapi]. – Peter Cordes Sep 05 '20 at 13:22
  • @MichaelPetch Im completly confused here. could please make an answer (with your code) that shows how to use my (Working Example) code with functions and calls? I just wanted to make my own function that shows `MessageBoxA` – Ali Sepehri-Amin Sep 05 '20 at 13:25
  • @MichaelPetch: 100% agreed with you on it being a mystery why the OP asked the question they did. My first reaction to how this question should be tagged was just based on a literal reading of exactly what they asked, in the initial form of the text, and before the self answer. Also before knowing that it wouldn't work with the same code in `.code`. (I assumed they'd taken a working example and broken it, not noticing the stack misalignment, and not knowing that MessageBoxA would care). As asked, it was really a very simple question, but one I assumed a beginner was curious about. – Peter Cordes Sep 05 '20 at 13:30
  • 1
    Now it's kind of a mess, especially with the self-answer to a different question, about the case where the code is all in `.code`, and giving the wrong reasons for why it works, opening up a whole can of worms about explaining tons of basics which the question as written still doesn't ask about. :( – Peter Cordes Sep 05 '20 at 13:30
  • This should work. It takes into account the stack alignment issues; the missing `ret` from the `msgbox_ready` function; moves the code out of the data section; and codes an appropriate way to exit the program. https://pastebin.com/LnDsa6L3 I will leave it up to someone else to explain the issue of stack alignment which are likely the root cause of most of your troubles. I'm busy for rest of the morning and do not have the time. – Michael Petch Sep 05 '20 at 13:56

1 Answers1

-2

I fixed the problem using jmp msgbox_ready instead of call msgbox_ready and the function is working fine. read Assembly 'call' vs 'jmp'

Ali Sepehri-Amin
  • 493
  • 1
  • 6
  • 18
  • That's not going to make it work with the function in `.data`. That *does* fix the stack-misalignment problem you introduced by not changing the `sub rsp, 28h` and not realigning the stack in `main` before `call msgbox_ready`, if the function is in `.code`. Apparently MessageBoxA from WinAPI does crash if you violate the calling convention that way by not having RSP aligned by 16 before a call. The question you linked doesn't say anything about stack alignment so it doesn't explain why a tailcall works. – Peter Cordes Sep 05 '20 at 13:00
  • @PeterCordes Im quite new to assembly. In my opinion, the difference between call and jmp is that `call` have to use for API or external calls (outside of the source code) and the `jmp` used for calling function (label) in source code and doesn't have return value. – Ali Sepehri-Amin Sep 05 '20 at 13:10
  • That's incorrect, you have to `call` your own functions if you want to be able to return from them at all, regardless of there being a return *value*. That's what makes it a separate function (although an optimized tailcall is still arguably to a different function). Look at compiler output, e.g. on https://godbolt.org/. You can also `jmp printf` tailcall any function you want, instead of `call printf` / `ret`. Since you aren't using `ret` after you calls, your code was already broken. – Peter Cordes Sep 05 '20 at 13:18