0

I am doing a class project which I am to take C code, turn it in x86-64 assembly and then change it to Y86. An in this I am suppose to return the sum of the elements in a linked list to to rax. However, when i try to use the y86 compiler, it doesn't appear. The y86 I made looked like this:

.pos 0
irmovq Stack,%rsp
irmovq Stack,%rbp
jmp Main

Main:
        irmovq ele1,%rax
        pushq %rax
        call sum_list
        halt

sum_list:
        pushq %rbp
        rrmovq %rsp,%rbp
        irmovq $24,%rdx
        subq %rdx,%rsp
        irmovq $0,%rdx
        rmmovq %rdx,-8(%rbp)
        jmp L2
L3:
        mrmovq 24(%rbp),%rax
        mrmovq (%rax),%rax
        mrmovq -8(%rbp),%rdx
        addq %rax,%rdx
        rmmovq %rdx,-8(%rbp)
        mrmovq 24(%rbp),%rax
        mrmovq -8(%rax),%rax
        rmmovq %rax,24(%rbp)
L2:
        irmovq $0,%rcx
        mrmovq 24(%rbp),%rdx
        subq %rcx,%rdx
        jne L3
        mrmovq -8(%rbp),%rax
        rrmovq %rbp,%rsp
        popq %rbp
        ret

#linked-list
.align 8
ele1:
        .quad 0x00d
        .quad ele2
ele2:
        .quad 0x0e0
        .quad ele3
ele3:
        .quad 0xf00
        .quad 0

.pos 0x500
Stack:

And so rax should have 0xfed, but in my result, nothing appears.

This is the C code I got it from:

typedef struct ELE{
  long val;
  struct ELE *next;
} *list_ptr

long sum_list(list_ptr ls){
  long val = 0;
  while(ls){
    val += ls->val;
    ls = ls->next;
  }
  return val;
}
Johan
  • 74,508
  • 24
  • 191
  • 319
Nukodi
  • 335
  • 1
  • 9
  • 24
  • Nobody wants to read that crappy un-optimized compiler output that stores everything to the stack after every statement. And what do you mean "nothing appears"? A register always has a value, even if it's zero. Are you sure you printed the result correctly? Did you look at RAX with a debugger? – Peter Cordes Oct 10 '16 at 00:01
  • BTW, normal style in C would be to make a typedef for the struct (not a pointer to the struct), and then write `const list_elem *p`. This makes it obvious that it's a pointer even before reading the name. When I look at `long sum_list(list_ptr ls)`, my initial impression is that it's a function that takes something by value. (Which is technically true; a pointer has a value.) – Peter Cordes Oct 10 '16 at 00:05
  • @PeterCordes I am using yas and yis to compile and execute my files. And it shows when registers are being changed. However, it doesn't show anything about %rax – Nukodi Oct 10 '16 at 00:08
  • 1
    `mrmovq -8(%rbp),%rax` should always run, even if the loop runs zero iterations. If you don't see that happen, you're doing something wrong, because there's no way out of the function that doesn't run that instruction. – Peter Cordes Oct 10 '16 at 00:28

1 Answers1

2

Looking at the code, it seems that the pointer to node should be at 16(rbp), not 24(rbp). 0(rbp) = saved rbp value, 8(rbp) = return address, 16(rbp) = pointer to node (to the linked list). I don't see where the extra 8 bytes are pushed onto the stack before rbp is saved.

The program ends at a halt instruction. Are you able to determine the content of rax when this happens (such as using a debugger)?

rcgldr
  • 27,407
  • 3
  • 36
  • 61
  • I think you're right, they're using the wrong RBP offset. It would make more sense to pass the function arg in RDI (like the x86-64 SystemV ABI does). I thought this stupid mess of code was supposed to be compiler output (obviously from `-O0` instead of `-O3`)? The OP said they used a y86 compiler, so IDK how this error was introduced. Anyway, I see the code do RSP -= 24, maybe that's where the 24 came from? `16(%rbp)` looks right to me. BTW, `$10` isn't `0x10` in gas syntax (I assume y86 is the same). gas AT&T syntax uses `$` on immediate constants. – Peter Cordes Oct 10 '16 at 00:26
  • Thanks for the comment about $ immediates. I removed that from my answer. Subtracting 24 from rsp doesn't affect rbp, so that's not the issue. – rcgldr Oct 10 '16 at 01:06
  • I was thinking that implementing the `RSP-=24` might have got the OP thinking `24` when they came to the part of the code that referenced the args. But I ran out of room in one comment make that clear. – Peter Cordes Oct 12 '16 at 04:07
  • @PeterCordes - that -24 could have been the source of confusion. Since the calling convention isn't specified, I don't the stack requirements. rsp-=8 would put rsp on a 32 byte boundary from it's original state, and would be enough for the one 8 byte variable (the -8(rbp)). rsp -= 24 subtracts an additional 16 bytes. – rcgldr Oct 12 '16 at 04:35
  • `gcc -O0` doesn't try very hard to minimize stack consumption. The whole code is a pile of garbage. A decent implementation wouldn't use any stack memory at all, and be maybe 3 to 5 times shorter and simpler. I'm glad I never had to do an assignment as un-fun as translating `-O0` x86 compiler output to y86. – Peter Cordes Oct 12 '16 at 04:41
  • @rcgldr Can you please take a look https://stackoverflow.com/questions/70919423/y86-instructions-set-create-confusion – Encipher Feb 03 '22 at 00:09
  • @Encipher - I don't know Y86. – rcgldr Feb 04 '22 at 15:20