diff --git a/Cargo.lock b/Cargo.lock
index 557319c6df231f95c8c888aeafe9a7ad72026976..ab929b2e2dd5716bc56821f027170140a0fb4b19 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -446,6 +446,7 @@ version = "0.1.0"
 dependencies = [
  "cbindgen 0.5.0",
  "platform 0.1.0",
+ "string 0.1.0",
  "va_list 0.1.0",
 ]
 
diff --git a/src/stdio/Cargo.toml b/src/stdio/Cargo.toml
index e64c0df1a573822c7169f99b5041c08070749bbb..570e409bd012b742ed12e710775ae776bf39da35 100644
--- a/src/stdio/Cargo.toml
+++ b/src/stdio/Cargo.toml
@@ -10,3 +10,5 @@ cbindgen = { path = "../../cbindgen" }
 [dependencies]
 platform = { path = "../platform" }
 va_list = { path = "../../va_list", features = ["no_std"] }
+string = { path = "../string" }
+errno = { path = "../errno"}
diff --git a/src/stdio/src/lib.rs b/src/stdio/src/lib.rs
index 7ac9d8170dc991fd7033a78d1bfb98199085e9fb..1f166000216c8899d1f4dfa3c7787b5d90fcc557 100644
--- a/src/stdio/src/lib.rs
+++ b/src/stdio/src/lib.rs
@@ -4,10 +4,16 @@
 
 extern crate platform;
 extern crate va_list as vl;
+extern crate string;
+extern crate errno;
 
-use core::slice;
+use core::str;
+use core::fmt::Write;
 
 use platform::types::*;
+use platform::c_str;
+use platform::errno;
+use errno::STR_ERROR;
 use vl::VaList as va_list;
 
 mod printf;
@@ -203,8 +209,23 @@ pub extern "C" fn pclose(stream: *mut FILE) -> c_int {
 }
 
 #[no_mangle]
-pub extern "C" fn perror(s: *const c_char) {
-    unimplemented!();
+pub unsafe extern "C" fn perror(s: *const c_char) {
+    let mut buf: [u8; 256] = [0; 256];
+
+    let mut sw = platform::StringWriter(buf.as_mut_ptr(), buf.len());
+
+    if errno >= 0 && errno < STR_ERROR.len() as c_int {
+        sw.write_str(STR_ERROR[errno as usize]);
+    } else {
+        sw.write_fmt(format_args!("Unknown error {}", errno));
+    }
+
+    let mut w = platform::FileWriter(2);
+    w.write_fmt(format_args!(
+        "{}: {}\n",
+        str::from_utf8_unchecked(c_str(s)),
+        str::from_utf8_unchecked(c_str(buf.as_mut_ptr() as *mut c_char))
+    ));
 }
 
 #[no_mangle]
diff --git a/tests/error.c b/tests/error.c
index 67fb25ed394c43fb1771d8bf2ec897097ca5fe75..9ab04c2bd967a08d2d8089c8d94deb00c31266d3 100644
--- a/tests/error.c
+++ b/tests/error.c
@@ -6,4 +6,5 @@
 int main(int argc, char** argv) {
     chdir("nonexistent");
     printf("errno: %d = %s\n", errno, strerror(errno));
+    perror("perror");
 }