Why can't I do without a variable?

enter image description here

include E:\masm32\include\masm32rt.inc HeapAlloc PROTO STDCALL :DWORD,:DWORD,:DWORD myfree proto :DWORD .data hmyHeap dd 0 hConsoleOutput DWORD ? adres DWORD ? hMylp1 dd 0 szCALL MACRO sz CALL @F BYTE sz, NULL @@: ENDM .code main: invoke AllocConsole invoke GetStdHandle, STD_OUTPUT_HANDLE mov hConsoleOutput, EAX invoke GetProcessHeap mov hmyHeap,eax invoke HeapAlloc,hmyHeap,HEAP_ZERO_MEMORY,300h mov hMylp1,eax szCALL "string" mov adres, esp push 7 push adres push eax call RtlMoveMemory mov ebx, [hMylp1] invoke WriteConsoleA, hConsoleOutput, ebx, 7, 0, 0 invoke HeapFree,hmyHeap,NULL,hMylp1 ret end main 

But if you do this with the messagebox, then everything is OK

  всё одно и тоже что и в коде выше ... push 0 push 0 szCALL "string" push 0 call MessageBox 
  • @Mike so everything is so bad? 🙁 - alex-rudenkiy
  • I did not understand why in the case of msgbox you wrote szCALL in the right place, so that he himself would put a parameter on the stack. And in the case of copying it was written incomprehensibly with the esp register and variable. Here stupidly by analogy with msgbox should be something like push 7; szCALL "string"; push eax; call push 7; szCALL "string"; push eax; call push 7; szCALL "string"; push eax; call - Mike
  • @MIke thank you, it helped, or rather earned, issue a nice answer and I will put the topic as decided: D - alex-rudenkiy

1 answer 1

The szCALL macro makes a rather tricky "hack", it defines a region with data directly in the code segment and executes a call to the instruction immediately following this data. The call instruction is practically jmp at the specified address, with push <адрес-след-инструкции> (i.e. it puts the return address on the stack). In the case of szCALL address of the next "instruction" is the address of the generated string, which is szCALL stack. If we want to pass this address as an argument to some sort of function, it should be on the stack. To pass the address of the string as an argument to RtlMoveMemory, we just need to specify it in the right place, among other arguments:

 push 7 szCALL "string" push eax call RtlMoveMemory 

Although calling the WinAPI function in order to put in the memory area a short line of 7 bytes is really too much. One could write something like (eax is the memory address where we put the string):

 mov dword ptr [eax], "irts" ; Да, байты на intel платформе в обратном порядке mov word ptr [eax+4],"gn" mov byte ptr [eax+6],0 
  • Elegant explanation 😀👍 - alex-rudenkiy
  • Here at the localization of programs without source codes for the last example I want to kill the compiler, which is so optimized) - insolor
  • @insolor I didn’t understand, where does some kind of optimization by the compiler, this is an assembler, and platform-specific, all optimization by hand - Mike
  • @Mike, I came across cases when the compiler produced such code. Well, or copying a string from one place in memory to another by several mov commands through registers. This is all good, it is performed fairly quickly, but it causes problems when you want to more or less automatically replace the original strings in the binary with others. - insolor