1

I wrote some simple assembly code like below:

.global _start

.text
_start:
    call _sum
    subq $0x8, %rsp
    popq %rax
    ret
_sum:
    ret

In order to get the value of %rax after 'popq' instruction,

I assembled that code using 'as' and 'ld' command. and I started gdb debugger by putting break point at '_start'

and the result comes like below:

B+> │0x400078 <_start>       callq  0x400083 <_sum>                            
│   │0x40007d <_start+5>     sub    $0x8,%rsp                                  
│   │0x400081 <_start+9>     pop    %rax                                       
│   │0x400082 <_start+10>    retq                                              
│   │0x400083 <_sum>         retq 

However, before going into pop instruction, There comes an error message saying that

Program received signal SIGSEGV, Segmentation fault. Cannot access memory at address 0x1

(when I changed the $0x8 into $0x0~$0x7, it all worked.)

It seems like at the first stage the sum function might be the problem. because It literally does nothing but return.

So, How can I modify this code to get the value of %rax after the popq instruction?

Thanks.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Parine
  • 71
  • 6

1 Answers1

3

I think probably this question is a duplicate, but anyway, there is one problem in your code.

.global _start

.text
_start:
    call _sum
    subq $0x8, %rsp
    popq %rax
    ret # <-- return to where?
_sum:
    ret

A main in C has to can return because _start eventually calls main, but here, you are writing _start directly. It returns to nowhere if you put a ret.

In place of ret, put this instead.

movl $60, %eax # syscall number for sys_exit
movl $0, %edi # or whatever value you want your process
             # to return with from 0 to 255;
             # xor %edi, %edi is usually better if you want 0
syscall

Leave a comment if it still crashes.


BTW, I was assuming your platform is Linux (because of the AT&T syntax..). The syscalls can be different for a different platform.

xiver77
  • 2,162
  • 1
  • 2
  • 12
  • I thought It worked at first, but when I put next instructions, there comes an error saying [Inferior 1 (process 8194) exited normally] /build/gdb-veKdC1/gdb-8.1.1/gdb/thread.c:1076: internal-error: void finish_thread_state(ptid_t): Assertion `tp' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. The error point is right after the sub instruction. and the result is same when I replace "mov $0, %edi" into "xor %edi, %edi" – Parine Mar 13 '22 at 09:52
  • @Parine What are your "next instructions"? It will not crash if you write something like [this](https://godbolt.org/z/nPqz6d8x4). If your "next instructions" are something that you didn't write in this question, then it should be a new question. See [this](https://godbolt.org/z/T96ohcoqo) if you must use AT&T syntax.. – xiver77 Mar 13 '22 at 10:05
  • Oh, since I am using with gdb debugger, I meant 'ni' utility for next instuction, (or 'step' ) If it works in your env, then what does the %rax value look like? cus the different error pops up on my env. – Parine Mar 13 '22 at 10:08
  • @Parine `rax` must hold `start + 5` which is where `sum` returns to. If it doesn't, you wrote something wrong. Could you show your whole code with a link to [Godbolt](https://godbolt.org/z/Ya4ahbcTd)? Copy paste your code and click "Share". – xiver77 Mar 13 '22 at 10:16
  • Oh also the GDB instruction for single stepping an assembly instruction is `si` not `ni`. – xiver77 Mar 13 '22 at 10:22
  • https://godbolt.org/z/hh13jf435 <-here. The error I am saying is during gdb debugger. Until assembling and loading (using 'as', 'ld'), there were no problems. Thanks for your help anyway. – Parine Mar 13 '22 at 10:22
  • Oh, sorry Now I got your point. I should have used si instead of ni. It all works now Thank you very much – Parine Mar 13 '22 at 10:26
  • 1
    @Parine I usually never write AT&T syntax so I forgot writing `movl`, `xorl` instead of `mov`, `xor`, although most assemblers will forgive this anyway. – xiver77 Mar 13 '22 at 10:26
  • @xiver77: Your original code with `mov $60, %eax` was 100% fine. I never both with operand-size suffixes in AT&T when a register already implies it. Some compilers and disassemblers always redundantly use suffixes, some only when there would be ambiguity without it like in `mov $1, (%rdi)`. Both are valid styles, and if you're used to Intel syntax the only-when-ambiguous style feels more natural. – Peter Cordes Mar 13 '22 at 16:04