1

I want to output a string to stdout by calling linux 0x80 interrupt, but when I use the char array as an argument, it cannot produce output.

When I use the char pointer variable as a parameter, there is no problem.

This is my code(file:c.c). The output is print "cd" not "abcd".

void prints(char *str, int size){
    asm(
        "movl $4, %%eax \n\t"
        "movl $1, %%ebx \n\t"
        "movl %0, %%ecx \n\t"
        "movl %1, %%edx \n\t"
        "int $0x80 \n\t"
        ::"m"(str), "m"(size)
       );

    return;
}

int main(){
    char str[] = {'a', 'b', '\0'};
    char *str1 = "cd";
    prints(str, 3);
    prints(str1, 3);
}

I use gcc -S c.c, the output file c.s like this. I still can't understand why "ab" does not output.

    .file   "c.c"
    .text
.globl prints
    .type   prints, @function
prints:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    movl    %esi, -12(%rbp)
#APP
# 2 "c.c" 1
    movl $4, %eax 
    movl $1, %ebx 
    movl -8(%rbp), %ecx 
    movl -12(%rbp), %edx 
    int $0x80 

# 0 "" 2
#NO_APP
    nop
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   prints, .-prints
    .section    .rodata
.LC0:
    .string "cd"
    .text
.globl main
    .type   main, @function
main:
.LFB1:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $16, %rsp
    movb    $97, -16(%rbp)
    movb    $98, -15(%rbp)
    movb    $0, -14(%rbp)
    movq    $.LC0, -8(%rbp)
    leaq    -16(%rbp), %rax
    movl    $3, %esi
    movq    %rax, %rdi
    call    prints
    movq    -8(%rbp), %rax
    movl    $3, %esi
    movq    %rax, %rdi
    call    prints
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1:
    .size   main, .-main
    .ident  "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-18)"
    .section    .note.GNU-stack,"",@progbits
  • Because you are generating 64-bit code and using 32-bit pointers and the 32-bit system call interface (int 0x80). The stack pointer where `ab\0` is stored can't be represented in a 32-bit pointer. You'll need (and should) to use `syscall` for 64-bit code instead of `int $0x80`. For more information on using `syscall` see [Ryan Chapman's blog](http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/) – Michael Petch Jun 03 '18 at 14:31
  • 1
    On top of my last comment you also need to be careful. If your inline assembly modifies the values of registers it needs to tell the compiler that. Either use proper output (or input/output) constraints or list them as clobbers. – Michael Petch Jun 03 '18 at 14:34

0 Answers0