0 Replies - 304 Views - Last Post: 16 October 2017 - 06:21 PM

#1 freeandme  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 27-September 17

Converting from x86 to x86-64

Posted 16 October 2017 - 06:21 PM

For an assignment, I need to port my code from x86 to x86-64. It's meant to reverse a linked list. I'm super confused as to what exactly everything means (this is one of my first assignments in assembly). I understand the basic logic of it all (basically just following the reverse_C function below), but I guess I'm having trouble understanding how to pass in and return values. I know that in x86-64, the registers are prefixed with r instead of e, that rax is the return value, and that the first parameter is passed in with rdi. However, when I tried to make these simple changes, I keep on getting a segmentation fault. I keep searching around to see if there's anything else I should change, but everything I read is really confusing to me. Can someone please explain what else I should do, and explain why my code as it is right now isn't working?

driver.c:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include "node.h"

extern Node* reverse_asm(Node *head, unsigned int offset);

#define NUM_NODES 20

int timeval_subtract(struct timeval *result, struct timeval *t2, struct timeval *t1)
{
    long int diff = (t2->tv_usec + 1000000 * t2->tv_sec) - (t1->tv_usec + 1000000 * t1->tv_sec);
    result->tv_sec = diff / 1000000;
    result->tv_usec = diff % 1000000;

    return (diff<0);
}

void timeval_print(char *str, struct timeval *tv)
{
    printf("%s %ld sec, %06ld micro sec\n", str, tv->tv_sec, tv->tv_usec);
}

Node *get_head(void *p)
{
        return p == NULL ?
                NULL :
                ((Node *)((char *)(p)-(unsigned long)(&((Node *)0)->ptr)));
}

Node *gen_rand_list(unsigned int count)
{
        Node *head, *tail, *curr;
        void *p;
        unsigned int i;

        head = tail = curr = NULL;
        srand(time(NULL));
        for(i = 0; i < count; i++) {
                curr = (Node *) malloc (sizeof(Node));
                memset(curr, 0, sizeof(Node));
                curr->var = curr->val.n = rand() % 1000;
                if(head == NULL) {
                        head = tail = curr;
                } else {
                        tail->ptr = &(curr->ptr);
                        tail = curr;
                }
        }
        return head;
}

void print_node(Node *node)
{
        printf("%d", node->var);
}

void print_list(Node *head)
{
        while(head) {
                print_node(head);
                printf(" -> ");
                head = get_head(head->ptr);
        }
        printf(" NULL\n");
}

Node *reverse_C(Node *head)
{
        void *headptr, *nextptr, *new_headptr;

        headptr = nextptr = new_headptr = NULL;
        if(head == NULL) return NULL;
        headptr = &(head->ptr);
        while (headptr) {
                nextptr = (void *)(*((unsigned long *)headptr));
                *(unsigned long *)headptr = (unsigned long) new_headptr;
                new_headptr = headptr;
                headptr = nextptr;
        }
        return get_head(new_headptr);
}

int main()
{
        struct timeval tvDiff, tvStart, tvEnd;
        Node *head, *revhead;

        /* This is the offset from base of node structure to the ptr field */
        unsigned int offset;
        
        /* We ask the compiler: "If 0 were the address of a Node, what is the address of ptr field?" */
        offset = (unsigned int)(&((Node *)0)->ptr);

        head = gen_rand_list(NUM_NODES);
        print_list(head);
        revhead = reverse_asm_64(head, offset);
        printf("****REV****\n");
        print_list(revhead);
        return 0;
}



My x86 (working):

.intel_syntax noprefix
.text
.global reverse_asm

reverse_asm:
push ebx

mov eax, 0x0
mov ebx, eax
mov ecx, eax
mov edx, eax
mov eax, [esp + 0x8]
cmp eax, 0
je null_ret

add eax, [esp + 0xC]
mov ebx, eax

while_start:
#ebx = headptr
cmp ebx, 0x0
je while_done

#ecx = nextptr
mov ecx, [ebx]

#edx = new_headptr
mov [ebx], edx
mov edx, ebx
mov ebx, ecx

jmp while_start

while_done:
mov eax, edx
sub eax, [esp + 0xC]

null_ret:
pop ebx
ret


My x86-64 (***not working***):

.intel_syntax noprefix
.text
.global reverse_asm_64

reverse_asm_64:
push rbx

mov rax, 0x0
mov rbx, rax
#nextptr
mov rcx, rax
#new_headptr
mov rdx, rax
#head
mov rax, [rsp + 0x8]
mov rax, rdi
cmp rax, 0x0
je null_ret

add rax, [rax + 0xC]
mov rbx, rax

while_start:

cmp rbx, 0x0
je while_done

mov rcx, [rbx]

mov [rbx], rdx
mov rdx, rbx
mov rbx, rcx

jmp while_start

while_done:
mov rax, rdx
sub rax, [rsp + 0xC]

null_ret:
pop rbx
ret



Is This A Good Question/Topic? 0
  • +

Page 1 of 1