-1

So far i have the following code:

char* s;
s = new char[10];

__asm
{       
    mov ebx, s
    mov byte ptr[ebx], 0x48       ;'H'
    mov byte ptr[ebx + 1], 0x65   ;'e'
    mov byte ptr[ebx + 2], 0x6C   ;'l'
    mov byte ptr[ebx + 3], 0x6C   ;'l'
    mov byte ptr[ebx + 4], 0x6F   ;'o'
    mov byte ptr[ebx + 5], 0x0A   ; 'new line'
    mov byte ptr[ebx + 6], 0;
    mov eax, ebx
    push eax
    call DWORD ptr printf
    pop ebx  
}

I'd like to declare a char array in asm not using DB, how would that look like?

user3813360
  • 566
  • 9
  • 25
  • 1
    You haven't provided enough specifics for your question. What memory allocation are you talking about? You want memory allocation in both assembly language, and `printf()`? That really doesn't make sense because one is a language, and one is a standard C function. – Jonathan Wood Nov 21 '19 at 17:22
  • no i'm sorry i worded it badly, i want to make the memory allocation for the char array in asm and after that make the call to printf – user3813360 Nov 21 '19 at 17:30
  • Are you asking how to declare an array of characters in assembly language? Or are you asking how to dynamically allocate the array at run time? – Jonathan Wood Nov 21 '19 at 17:33
  • If you are asking how to declare an array of characters, see [this question](https://stackoverflow.com/questions/41647537/using-db-to-declare-a-string-in-assembly-nasm). – Jonathan Wood Nov 21 '19 at 17:34
  • i want to declare a char array with a specific size: (char* s; s = new char[10]) – user3813360 Nov 21 '19 at 17:42
  • `call printf` ? – S.S. Anne Nov 21 '19 at 17:55
  • no i don't want to declare it the NASM way – user3813360 Nov 21 '19 at 17:59
  • 2
    Why? It's *inline* assembly, as opposed to standalone, much easier to drop back into to C for printing. Also, what does NASM have to do with it? Inline assembly is usually assembled by the compiler. The C compiler in your case. – Seva Alekseyev Nov 21 '19 at 18:01
  • The simple way would be to call `malloc` in your assembly code, much the same way you're calling `printf`. Except you should just use `call malloc` and `call printf`. – Ross Ridge Nov 21 '19 at 20:11
  • You said "declare". Do you mean declare it from inside the `_asm{}` *so you can access it later from C* as a named C variable? That's impossible. You could reserve a buffer on the stack, though, and deallocate it before the end of your asm block. In that case see [Defining a variable inside c++ inline assembly](//stackoverflow.com/q/1396265) – Peter Cordes Nov 21 '19 at 21:17

2 Answers2

0

possible also this way:

call do_print
db "Hola...Hello", 0Ah,0
do_print:
call DWORD ptr printf
pop rcx

while making call to do_print we put to the stack return address what is in fact start address of our buffer "Hello..", so simple in assembler, changed to pop rcx instead pop [esp]

  • 2
    While this code snippet may be the solution, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. – CEH Nov 25 '19 at 19:18
  • This is broken; you forgot to pop the string pointer (pushed by the first `call`) off the stack before leaving the inline `asm` statement. You need a dummy pop (like `pop ecx`) at the end, or `add esp,4`. Also this unbalanced the return-address predictor so the `ret` at the end of the containing function will mispredict as going to the `db`, and future `ret`s back up the call tree will also mispredict. – Peter Cordes Nov 26 '19 at 08:59
  • call DWORD ptr printf is stdcall regarding the question, and call do_printf puts the address of the string into stack, sorry, u right it's __cdecl, pop something at the end – Natascha Koschkina Nov 26 '19 at 09:59
  • variadic functions are never stdcall. It's C UB to call printf with the wrong number or type of args so in theory it could be, but in practice it's not convenient to make a function that pops a variable size as its returning. `ret imm16` only takes and immediate, and you don't want `pop ecx` / `add esp, edx` /`jmp ecx` because that would unbalance the return-address predictor stack. Also, too much code depends on printf silently ignoring extra args. Perhaps use `puts` so you can omit the `\n` as well. – Peter Cordes Nov 26 '19 at 13:47
  • `pop dword ptr [esp]` is less efficient than `add esp,4`. Only a dummy pop into a *register* would make sense. Anyway, your answer still doesn't explain why this works (that `call` pushes a pointer to the string), or the performance downside. – Peter Cordes Nov 26 '19 at 13:49
  • @Peter Cordes call to the function put the return address on the stack and this address is your string "Hello", simple and short, pop [esp] is also shorter, and it doesn't uses any registers but u can make add esp, 4 – Natascha Koschkina Nov 26 '19 at 14:29
  • *I* know how it works, but **your answer doesn't say that**. Put your answer in your answer, not comments. Anyway, `pop [esp]` is 3 bytes (opcode + modrm + SIB because of using ESP as a base register) vs. `add esp, 4` also being 3 bytes (opcode + modrm + imm8). They're the same length but `pop [mem]` is less efficient: 2 fused-domain uops for the front-end on Sandybridge-family: https://www.agner.org/optimize/instruction_tables.pdf. And probably an extra uop for stack engine sync because it does use ESP explicitly. vs. 1 uop for `add reg,imm`, of course. – Peter Cordes Nov 26 '19 at 14:38
  • ok, then lets do pop ecx or edx or pop eax in case of not interrested result of printf – Natascha Koschkina Nov 27 '19 at 06:57
  • @Peter Cordes btw. look what is about where the question? was it about performance? im not sure that on modern processors would be difference between pop reg and pop mem (prefetch, cache), you have disabled me from adding comments, I have trying to add comment to question and there was written that Im banned, ok – Natascha Koschkina Nov 28 '19 at 09:02
  • The main reason I downvoted this answer is that it doesn't include an explanation of how it works, or *why* you'd want to do it this way. We've discussed multiple aspects of that in comments but you still haven't [edit]ed your answer to improve it. I'd be happy to remove my downvote and maybe upvote it if you improve the things I pointed out. And BTW, see my previous comment: `pop reg` decodes to only 1 uop on modern CPUs, `pop [mem]` decodes to 2. And has worse code-size. So it's clearly slightly worse, and more complicated, and not a good recommendation for other people to copy. – Peter Cordes Nov 28 '19 at 09:17
  • Also: commenting under posts that aren't your own requires some rep; you weren't "banned" from it by getting downvotes, you couldn't in the first place until earning some upvotes. – Peter Cordes Nov 28 '19 at 09:19
-1

this is how i did it:

  push 0x6F
  push 0x6c6c6548
  push esp
  call DWORD ptr printf
  add esp, 12 
user3813360
  • 566
  • 9
  • 25
  • That reserves anonymous space for a buffer on the stack. That's what you actually want in this case, but it's not a *declaration* of any kind. You could say "create" but not declare. Still a duplicate of [Defining a variable inside c++ inline assembly](//stackoverflow.com/q/1396265) which shows reserving space on the stack. – Peter Cordes Nov 25 '19 at 00:49
  • Oh, modifying EBP inside inline asm will break any compiler-generated addressing modes for locals. If you wrote `mov ecx, my_local_var`, you'd load the wrong thing. Instead, `add esp, whatever` after your call to clean up the stack. Or use any other call-preserved reg like EDI instead of EBP. – Peter Cordes Nov 25 '19 at 00:53
  • Also, you don't need `push eax`; `push 'o'` is already a 4-byte push of a sign-extended immediate, so it stores `0x0000006F`. You also don't need to `sub esp, 16` to leave a gap above the literal string data you push: push already moves ESP for you, that's why it's called `push` not `mov [esp], 0x6c6c6548`. – Peter Cordes Nov 25 '19 at 00:54
  • so this would be alright? `push 0x6F push 0x6c6c6548 push esp call DWORD ptr printf add esp, 12` – user3813360 Nov 25 '19 at 16:07
  • Yup, looks sane to me. `printf` is variadic so it definitely doesn't remove its own args from the stack, so yes `add esp,12` removes the pointer and the string data. – Peter Cordes Nov 26 '19 at 01:27