CPSC 355: Tutorial 15
Syscalls and Assignment 6
PhD Student
Fall 2017
Outline
Assignment 6 (Newton's method) and System Calls
Assignment 6
Assignment 6 is a little more free form than the previous assignments
Basically, you have to read a list of numbers (from a file) and take their cube root.
- File I/O, note that we do this with syscalls, and you're not allowed to use fopen().
- Floating point arithmetic and registers
This assignment isn't that big, but has no starting C code.
Newton's Method
Newton's method finds zeros of a function \(f(x)\). Starting with some initial guess \(x_0\), we iteratively search for a zero of \(f(x)\).
\(x_{n+1} = x_n - \frac{f(x_n)}{f^\prime(x_n)}\)
\(f(x_{n}) \approx 0 \)
After some amount of iterations we have
How do we use this to calculate \(\sqrt[3]{a}\)?
Newton's Method
Let's state the problem slightly differently
We know \(a\), let's try to find \(x\). We don't know how to 'cube root' in a computer, but we can raise each side to the power of 3.
But now finding \(x\) is equivalent to finding zeros of the equation
Newton's Method
Now, if we define \(f(x) = x^3 - a\), and apply newton's method, we get
\(x_{n+1} = x_n - \frac{f(x_n)}{f^\prime(x_n)}\)
\(x_{n+1} = x_n - \frac{x_n^3 - a}{3x_n^2}\)
We take \(x_0 = \frac{a}{3} \) and stop iterating when \(\left|x_n^3 - a\right| < 1.0\times 10^{-10}\)
Newton's Method
If you follow the instructions on the A6 handout, your code will look something like this
Let's do this in C now...
System Calls
We've used the standard library to do simple I/O (printf, putch, scanf, etc..)
At the end of the day, we really have no idea how these functions interacted with the hardware.
In fact, we don't have permission to directly manipulate I/O. We have to ask the operating system to do this for us.
We do this via system calls
System Calls
We put the system call number into x8, the system call arguments into x0-x5, and execute a system call with the instruction svc.
These all have equivalent C functions as well.
System Calls
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd = openat(AT_FDCWD, "input.bin", O_RDONLY, 0666);
int bytes_read = 0;
double value = 0.0;
if(fd == -1) {
printf("Cannot open input.bin for reading!");
return -1;
}
bytes_read = read(fd, &value, sizeof(double));
printf("Read %f from input\n", value);
close(fd);
}
System Calls
.data
filename_str: .string "input.bin"
fmt1: .string "Cannot open input.bin for reading!\n"
fmt2: .string "Read %f from input\n"
.text
.balign 4
.global main
// Local variables
fd_o = 16
bytes_read_o = 20
value_o = 24
main:
stp x29, x30, [sp, -32]!
mov x29, sp
mov w0, -100 // mov AT_FDCWD = -100 into w0
ldr x1, =filename_str
mov w2, 0 // w2 = 0 (O_RDONLY)
mov w3, 0666 // w3 = permissions
mov x8, 56 // set x8 as 56 (openat) system call
svc 0 // openat(-100, filename_str, 0, 0666)
System Calls
str w0, [x29, fd_o] // store the handle
cmp w0, -1
b.gt read_value // if successful, jump to read value
// print the error message
ldr x0, =fmt1
bl printf
mov x0, -1 // setup return value of -1
b exit_main
read_value:
// setup for a read
ldr w0, [x29, fd_o] // w0 = fd
add x1, x29, value_o // x1 = address of value on the stack
mov w2, 8 // w2 = size to read (8 bytes)
mov x8, 63 // set x8 as 63 (read) system call
svc 0 // read(fd, &value, 8)
str w0, [x29, bytes_read_o] // store the bytes read
ldr x0, =fmt2 // Load format string
ldr d0, [x29, value_o] // load value into d0 register (we'll talk about
// these next day)
bl printf // printf("..", value);
System Calls
mov x0, xzr // setup return value of 0
exit_main:
// close the file
ldr w0, [x29, fd_o]
mov x8, 57
svc 0
ldp x29, x30, [sp], 32
ret
We used a double precision register d0 in this example. We have 32 double precision registers (d0-d31) and 32 single precision registers (s0-s31). But we'll talk about those next day.
Next Day
Floating point registers, and floating point arithmetic.
CPSC 355: Tutorial 15
By Joshua Horacsek
CPSC 355: Tutorial 15
- 1,828