0

So I have this C file where I am getting two strings of input from stdin and I am trying to pass them to my assembly code and have my assembly code determine if the first string would come after the second string in a dictionary and if so then return a 1.

#include <stdio.h>

extern int stringcheck(char *s1, char *s2);

int main(){
        char s1[30];
        fgets(s1, 31, stdin);
        char s2[31];
        fgets(s2, 31, stdin);
        int ret = stringcheck(s1, s2);
        if(ret == 1){
                printf("True\n");
        }
        if(ret == 0){
                printf("False\n");
        }
        return 0;
}

In this assembly code I tried to load my strings into appropriate registers and then use cmpsb in a loop and have the program jump to 'second' if the carry flag is set to 1. What happens though is that regardless of the string entered the program will always jump to the 'second' block and return 9 so I'm assuming I messed something up with how I prepared the strings to be checked.

    global stringcheck
    section .text
    stringcheck:

    ; save state of registers and setup stack frame
    push rbp
    mov rbp, rsp
    push rax
    push rbx
    push rdx

    lea rsi, [rbp+60] ; move first arg into rsi
    lea rdi, [rbp+30] ; move second arg into rdi

    mov rcx, 30 ; set up incrementer
    cld

    top:    cmpsb
    jc second
    loop top

    jmp first

    first:  pop rdx
    pop rbx
    pop rax
    mov rsp, rbp
    pop rbp
    mov rax, 1
    ret

    second: pop rdx
    pop rbx
    pop rax
    mov rsp, rbp
    pop rbp
    mov rax, 0
    ret
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Eup1
  • 1
  • 1
    Strings aren't passed directly as parameters. A pointer to the string is passed. The first parameters are passed in registers and the stack in 64-bit ABIs and it is dependent on OS. Windows uses one ABI and Linux/MacOS/BSD use another. What OS are you using? – Michael Petch Apr 26 '20 at 02:45
  • Arrays "decay" to pointers when you pass them to functions. You even declared your asm function as taking `char*` args. Your asm might work if the arrays were inside a `struct { char arr[30]; } array_by_value;` Except that it would still be passed on the stack aligned to a multiple of 8 bytes, starting above the return address. But anyway, on function entry RDI and RSI already hold `char*` function args. Look at the compiler-generated code for the caller; you should see it passing pointers. Also you can use a debugger to single-step the caller and step into your asm function. – Peter Cordes Apr 26 '20 at 02:45
  • Basically a duplicate of [passing an array of chars to external assembly function](https://stackoverflow.com/q/49618929) which shows compiler-generated code for the callee, but doesn't bother to explain anything. Related: [From compiler perspective, how is reference for array dealt with, and, why passing by value(not decay) is not allowed?](https://stackoverflow.com/q/50775127) also answers this. – Peter Cordes Apr 26 '20 at 02:55
  • @MichaelPetch I'm using Linux, also thank you I don't know why I forgot that it was passing a pointer and not an array. – Eup1 Apr 26 '20 at 03:33
  • That's why I added [What are the calling conventions for UNIX & Linux system calls on i386 and x86-64](https://stackoverflow.com/q/2535989) as a 3rd duplicate - it covers the function calling convention as well as system calls. Check it out, this is all well documented. (And you can look at compiler output to see where it passes args any time you aren't sure what the docs are saying.) – Peter Cordes Apr 26 '20 at 03:40
  • @PeterCordes sorry I saw that and tried to delete my comment before you replied to it but thank you for the help – Eup1 Apr 26 '20 at 03:44
  • 1
    Comments so far have focused on you reading the array from the wrong place. However, there's another problem: you don't stop when you see a null byte, so if two strings shorter than 30 bytes are equal, you'll start comparing the random memory after the null bytes. – Joseph Sible-Reinstate Monica Apr 26 '20 at 03:48

0 Answers0