Skip to main content

Lecture Notes: 07 Syscalls

··2 mins

lines.S

#include <stdio.h>

int
main(int argc, char* argv[])
{
    char* buf[128];
    FILE* msg = fopen("msg.txt", "r");
    int yy = fread(buf, 128, 1, msg); 
    buf[yy] = 0;
    printf("%s\n", buf);
    fclose(msg);
    return 0;
}
  • Talk about stdin, stdout, stderr
  • Talk about file descriptor table
  • Rewrite this with syscall wrappers.

/* lines.S - reads "msg.txt", counts lines ('\n' characters) */

  .global main
  .text
main:
  push %r14   /* file descriptor for msg.txt */
  push %r15   /* size of msg.txt contents */
  /* %rcx is loop counter */
  /* %rdx is count */
  /* %rax is current byte */
  enter $256, $0
  /* 0(%rsp) is read buffer, 192 bytes */
  /* 192(%rsp) is print buffer, 64 bytes */
  mov $intro, %rdi
  call strlen

  mov $1, %rdi       /* fd 1 is stdout */
  mov $intro, %rsi   /* buffer */
  mov %rax, %rdx     /* size */
  mov $1, %rax       /* syscall 1 is write */
  syscall

  mov $file, %rdi   /* file name */
  mov $0, %rsi      /* O_RDONLY ; see bits/fcntl-linux.h */
  mov $0, %rdx      /* mode is unused on read */
  mov $2, %rax      /* syscall 2 is open */
  syscall
  mov %rax, %r14    /* save fd */

  mov %r14, %rdi    /* read from file */
  lea 0(%rsp), %rsi /* read to stack */
  mov $192, %rdx    /* buffer size */
  mov $0, %rax      /* syscall 0 is read */
  syscall
  mov %rax, %r15    /* save bytes read */

  mov $0, %rcx
  mov $0, %rdx
loop_cond:
  cmp %r15, %rcx
  jge loop_done

  mov $0, %rax
  mov (%rsp,%rcx,1), %al

  cmp $'\n', %al
  jne loop_next

  inc %rdx

loop_next:
  inc %rcx
  jmp loop_cond

loop_done:
  lea 192(%rsp), %rdi
  mov $fmt, %rsi
  /* count already in %rdx */
  mov $0, %al
  call sprintf

  mov $1, %rdi        /* fd 1 is stdout */
  lea 192(%rsp), %rsi /* buffer */
  mov %rax, %rdx      /* size */
  mov $1, %rax        /* syscall 1 is write */
  syscall

  /* TODO: look up close syscall to close file */

  mov $0, %rdi
  mov $60, %rax   /* syscall 60 is exit */
  syscall

  leave
  pop %r15
  pop %r14
  ret

  .data
intro: .string "lines in msg.txt:\n"
file: .string "msg.txt"
fmt: .string "lines = %ld\n"

ref: https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/