0

I am trying to pass a char array into an x86_64 assembler program and modify it having the result available for printing in the calling c program. I am just learning assembler and haven't had much success accomplishing this. I am running Ubuntu 20.04 and using gcc and nasm compilers. The c program is as follows:

#include <stdio.h>

extern void task(char *str, char *buf);

int main(int argc, char** argv){
    if (argc || argv[0]){}
    printf("\n%s\n",argv[0]);
    char buffer[256] = {"LJKM"};

    task("ABCDEFG", buffer);
    printf("\n>>%s\n",buffer);
    return 0;
}

The assembler program so far is:

section .data
    string1 db  0xa, "  Hello StackOverflow!!!", 0xa, 0xa, 0

section .text
    global task

    task:
        push rbp
    mov rsi, qword(string1)



    
        pop rbp
        ret

I have run gdb and can see that the pointer to the string "LKJM" is passed to the assembler program in register rsi. And just prior to returning to the caller, the value pointed to by the register rsi is the "Hello Stackoverflow" string. but when the buffer is printed inside the caller, it is still "LKJM". Why doesn't the data persist? What is the correct way to accomplish this task?

-

dave4952
  • 1
  • 1
  • 1
    C functions pass by value unless you explicitly use pointers. RSI is not a return value. There's no way to write a C function that could affect where the caller's `buffer` arg points, only copy into the pointed-to memory. Look at compiler-generated code for examples, and read about the calling convention. – Peter Cordes Mar 11 '22 at 21:13
  • 1
    Also, I'm surprised `mov rsi, qword(string1)` even assembles. I guess NASM lets you put parens around any numeric constant, and `qword` there specifies the operand-size of the immediate (although that was already implied by the register). See [How to load address of function or label into register](https://stackoverflow.com/q/57212012) for the normal way to do that. – Peter Cordes Mar 11 '22 at 21:14
  • @PeterCordes Pointers are passed by value too. It's just that the value can be used to modify what is pointed to (unless it's a pointer to a const object). – user904963 Mar 12 '22 at 01:37
  • @user904963: Yes, but that's not what the asm is doing, and the querent even describes observing that the pointer value itself in RSI has changed and is now pointing somewhere else inside the callee. It seems to me the key disconnect is expecting this to affect the caller. (Although on 2nd look, the caller is passing the address of an array, not the value of a pointer variable, so there's no lvalue in the caller that even could be modified to hold a new pointer.) If the question described why they think this *should* work in C terms and in asm terms, then we could see the misunderstanding. – Peter Cordes Mar 12 '22 at 01:40
  • @user904963: And equally importantly, see whether they're trying to implement strcpy, or trying to return a pointer to different static storage and pass that pointer to printf. – Peter Cordes Mar 12 '22 at 01:43
  • @PeterCordes: I do not pretend to know how this is supposed to work. That is why I asked how should it be done. If you are passed a string and a char* buffer, how would you move the values in that string to the buffer inside of an assembler program. – dave4952 Mar 12 '22 at 15:38
  • Oh, so you're trying to implement `strcpy` (but with src, dst arg order). I had no idea from the question since there was no C equivalent, and the asm was using its own static string. Google on x86-64 asm strcpy, you should find lots of simple examples, including many on SO. – Peter Cordes Mar 12 '22 at 15:57
  • Or write a C version of your `task` function and look at compiler output. (That won't be NASM syntax, but should give you an idea what instructions to use. Compilers are really aggressive at optimizing copying so you might want to use `gcc -Og` in [How to remove "noise" from GCC/clang assembly output?](https://stackoverflow.com/q/38552116) – Peter Cordes Mar 12 '22 at 15:57

0 Answers0