0

I learned MIPS a few years ago in class and have been learning x86_64 recently. A lot of the general knowledge of assembly has transferred over, but the registers and stack are slightly different. I believe understand what and why I need to do, I'm just not sure how to do it.

As far as I'm aware, I need to subtract the stack pointer to open up writable space, write my data to it, and then access it in my function by adding the necessary offset. And from what I've read rbp is the base pointer and rsp is the top pointer. I've been messing around with different offsets though and my code is not printing anything or (in this iteration) segfaulting

section .data
        msg db 'Hello, world!', 0xa     ; set msg as text with trailing newline
        len equ $ - msg                 ; store length of msg
        outfile db 'test_file.txt', 0   ; set outfile as text without trailing newline
        msg1 db 'Hell2, world!', 0xa    ; set msg1 as text with trailing newline
    
    section .text                       
        global _start                   ; define symbol for entry point
        global exit                     ; define symbol for exit
        global print                    ; define symbol for print
    
    print:
        mov eax, 4      ; set instruction to write
        mov ebx, 1      ; set file descriptor to stdout
        mov ecx, msg    ; set buffer to msg
        mov ecx, [rbp+8]    ; set buffer to (ideally) msg1
        mov edx, len    ; set the size to the length of text
        int 0x80        ; system call
        ret             ; return to call location
    
        
    _start:
        sub rbp, len
        mov rsp, msg1
        call print      ;   call print function
        jmp exit        ;   jump to program exit code
    
    
    exit:
        mov eax, 1          ; set instruction
        mov ebx, 0          ; program exit code
        int 0x80            ; system call
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
P O
  • 13
  • 4
  • `mov rsp, msg1` causes the stack pointer to point *to* `msg1`. Obviously this won't work because now future pops will be fetched from the data section, where they were never pushed. Is your goal to *copy* the string `msg` onto the stack? You will need to decrement `rsp` by `len` (rounded up to a multiple of 16) and then use a loop or `rep movsb` or similar to copy the bytes of the string. – Nate Eldredge Mar 18 '22 at 15:54
  • 1
    First of all, [generally avoid `int 0x80` 32-bit system calls in 64-bit code](https://stackoverflow.com/questions/46087730/what-happens-if-you-use-the-32-bit-int-0x80-linux-abi-in-64-bit-code). Also, `mov rsp, msg1` points your stack pointer into .data, so the `call` will push a return address that overwrites some of the bytes at `outfile:` – Peter Cordes Mar 18 '22 at 15:55
  • 1
    On the other hand, it's not necessary to copy the string at all: you can `write` it perfectly well by just giving the system call a pointer to its current location at `msg`. Are you trying to copy just for the practice? – Nate Eldredge Mar 18 '22 at 15:57
  • `sub rbp, len` never makes sense; you don't move RBP (the frame pointer), only RSP to make space below RBP. (And only if RBP is set up as a frame pointer, but your code didn't do `mov rbp, rsp` before that, so on entry to `_start` you probably just have RBP=0. – Peter Cordes Mar 18 '22 at 15:57
  • Oh, you're trying to pass the pointer to `print` via the stack. That isn't the usual calling convention on x86-64: the first several arguments are passed in registers. You aren't bound by usual calling conventions if you're writing your own code in assembly, but even so there is no good reason to use the stack at all here; you have plenty of registers to pass data around. – Nate Eldredge Mar 18 '22 at 15:59
  • I appreciate the informative and detailed comments and the bugs now make more sense. I now plan on fixing the bugs and updating my system calls to 64-bit as I've realized that I am basically writing 32-bit code compiled to 64-bit. I was also wondering if @PeterCordes or Nate Eldredge were aware of good starter resources for learning x86-64 as I plan on developing both a compiler and operating system with it, but I am clearly only at the beginning of these ventures. – P O Mar 18 '22 at 16:08
  • 1
    There are some tutorial links in https://stackoverflow.com/tags/x86/info as well as manuals and stuff. – Peter Cordes Mar 18 '22 at 16:11
  • Just consider `rbp` as a normal register. (The encoding gets different when it's used as the base pointer in a memory operand, but this detail is negligible in most cases.) Compilers also use `rbp` as a free (callee-saved) register with optimization on. Maybe there's some historic reason that `rbp` is considered some special register like `rsp`, but there is no reason to do so in 64-bit mode. – xiver77 Mar 18 '22 at 18:17
  • I correct myself for saying there is "no reason" to treat `rbp` specially. Doing `push rbp; move rbp, rsp` or `enter` at the beginning of every function is one way of doing stack unwinding, so it can be useful for debug builds. Modern systems have different ways to do this such as the `.eh_frame` section on Linux. – xiver77 Mar 18 '22 at 21:50

0 Answers0