0

I'm trying to compare the first character of the first struct in list with the first character of token in assembly. However, the two characters are never equal for some reason. I know the first char in the first student is the same as the first char in token.

struct student
{
  long    ID;          /* 8 bytes in 64-bit */
  char    name[24];
};

/*
* list - the starting address of the list of structures to be searched
* count - total number of names in list
* token - name to be searched in the list
*/
long search_by_name (char* list, long count, char* token)
{
    long index = 0;

asm
(
    "movq %1, %%rax;" // list to rax       
    "movq %2, %%rbx;" // token to rbx
    "movq %3, %%rcx;" // count to rcx 

    "movq 8(%%rax), %%rsi;" // Offset rax by 8 to get to first char in struct
    "movq (%%rbx), %%rdi;" // Move memory address rbx into rdi
    "cmpq %%rdi, %%rsi;" // Compare the two chars
    "je equals;"         // Two chars are never equal for some reason

    "jmp finish;"

"equals:"
    "movq 0(%%rax), %%rax;"
    "jmp finish;"

"finish:"
      : "=a" (index)
     : "r" (list), "r" (token), "r" (count)
     : 
     );
     return index;
}
What it's supposed to do in C:

struct student *clist = (struct student*)list;
for (index = 0; index < count; index++)  
    if ( strcasecmp( clist[index].name, token ) == 0)
        return clist[index].ID;
return 0;

The C code is what the end result is supposed to be, but I'm still trying to figure out how to compare clist[index].name and token. How would I compare the struct char array with the token char*?

Edit: Comparison worked after changing it to:

movq 8(%%rax), %%r10; 
movq (%%rbx), %%r11; 
cmpb %%r10b, %%r11b;
Arkitek
  • 3
  • 2
  • Why is `list` a `char*` and not a `struct student*`? And where's the code where you call `search_by_name`? – Joseph Sible-Reinstate Monica Apr 25 '20 at 00:32
  • `list` is a `char*` that points to an array of structures and `search_by_name` is called in a main method too long to post here. You can assume that the main method works as intended. The only problem is comparing the first character of the first `student` in `char* list` with `char* token`. – Arkitek Apr 25 '20 at 00:40
  • Your asm statement doesn't declare clobbers on any of the hard-coded registers you picked (other than the `"=a"` output), and no `"memory"` clobber to tell the compiler that memory pointed-to by input operands is also an input. [How can I indicate that the memory \*pointed\* to by an inline ASM argument may be used?](https://stackoverflow.com/q/56432259). – Peter Cordes Apr 25 '20 at 00:55
  • Also the actual asm looks buggy: the comments say "compare two chars" but you've actually loaded 8 bytes of char data from each. This would be obvious if you single-stepped your code with a debugger and looked at registers. Also, you could simplify `je equals` to just use `jne finish` instead of jumping over a `jmp`. – Peter Cordes Apr 25 '20 at 00:56
  • Can you write `search_by_name` in pure C, and edit that into your question? That might make it more clear what you're going for. – Joseph Sible-Reinstate Monica Apr 25 '20 at 01:19
  • I added the C code to the bottom. – Arkitek Apr 25 '20 at 01:29

1 Answers1

1

Two main problems: First, cmpq compares the first 8 characters, not just one. Second, when the comparison fails, you return the pointer list, rather than any sort of sentinel.

Also, you're clobbering a bunch of registers but not letting GCC know. After your last :, add "rbx", "rcx", "rsi", "rdi", "cc", "memory".

  • I return pointer `list` because it points to the first struct in the `list`. It's just a placeholder until I figure out how to compare the `char[]` in the first struct with the `char* token`. – Arkitek Apr 25 '20 at 01:19
  • I took what you said about how cmpq compares the first 8 characters and after looking at my notes, I changed it so that it compares byte 0 instead. It works after changing it to: `movq 8(%%rax), %%r10; movq (%%rbx), %%r11; cmpb %%r10b, %%r11b;` – Arkitek Apr 25 '20 at 02:14