diff --git a/nemu/include/macro.h b/nemu/include/macro.h
index 68b9399fb591ac99a8541e769c66d78df12e9d6b..2bc2d2b77ec74ecb6a2dde413b3d531610c84ea9 100644
--- a/nemu/include/macro.h
+++ b/nemu/include/macro.h
@@ -15,4 +15,7 @@
 #define RLIB_MACRO_DEBUG_ASSERT(expr)
 #endif
 
+#define RLIB_MACRO_LIKELY(x)       __builtin_expect((x),1)
+#define RLIB_MACRO_UNLIKELY(x)     __builtin_expect((x),0)
+
 #endif
diff --git a/nemu/src/device/io/mmio.cc b/nemu/src/device/io/mmio.cc
index 529845fe4d038ed724a139a22c0f3f63fbea9ceb..396f0ede02f279af5758403e9c2788806fa702c4 100644
--- a/nemu/src/device/io/mmio.cc
+++ b/nemu/src/device/io/mmio.cc
@@ -33,7 +33,7 @@ void* add_mmio_map(paddr_t addr, int len, mmio_callback_t callback) {
 }
 
 /* bus interface */
-int is_mmio(paddr_t addr) {
+__attribute__((hot)) int is_mmio(paddr_t addr) {
   int i;
   for (i = 0; i < nr_map; i ++) {
     if (addr >= maps[i].low && addr <= maps[i].high) {
diff --git a/nemu/src/memory/memory.cc b/nemu/src/memory/memory.cc
index 5fb2155def3c9ab4487f22957523225ff60945a7..8bce9de0feab69e7e41135d967b52e29ecc87391 100644
--- a/nemu/src/memory/memory.cc
+++ b/nemu/src/memory/memory.cc
@@ -1,4 +1,5 @@
 #include "nemu.h"
+#include "device/mmio.h"
 
 #define PMEM_SIZE (128 * 1024 * 1024)
 
@@ -13,21 +14,25 @@ uint8_t pmem[PMEM_SIZE];
 
 __attribute__((hot)) uint32_t paddr_read(paddr_t addr, int len) {
     static const uint32_t niddle[] = {0, 0xff, 0xffff, 0xffffff, 0xffffffff};
-    return pmem_rw(addr, uint32_t) & niddle[len];
-//  switch(len) {
-//    case 4: return pmem_rw(addr, uint32_t);
-//    case 2: return pmem_rw(addr, uint32_t) & 0x0000ffff;
-//    case 1: return pmem_rw(addr, uint32_t) & 0x000000ff;
-//    case 3: return pmem_rw(addr, uint32_t) & 0x00ffffff;
-//    case 0: return 0;
-//  }
-//  return pmem_rw(addr, uint32_t) & (~0u >> ((4 - len) << 3));
+
+    if(const auto mmio_id = is_mmio(addr);(-1 == mmio_id)) {
+      return pmem_rw(addr, uint32_t) & niddle[len];
+    }
+    else {
+      return mmio_read(addr, len, mmio_id);
+    }
 }
 
 void paddr_write(paddr_t addr, uint32_t data, int len) {
-  memcpy(guest_to_host(addr), &data, len);
+  if(const auto mmio_id = is_mmio(addr);(-1 == mmio_id)) {
+    memcpy(guest_to_host(addr), &data, len);
+  }
+  else {
+    mmio_write(addr, len, data, mmio_id);
+  }
 }
 
+
 // len is Bytes.
 uint32_t vaddr_read(vaddr_t addr, int len) {
   return paddr_read(addr, len);
diff --git a/nexus-am/am/arch/x86-nemu/src/devices/input.c b/nexus-am/am/arch/x86-nemu/src/devices/input.c
index a0634a778d2e26d2d6c72da0998d30e2d0cfebbc..15173f5d216813888cb8f3f5cf22a417e48ff7be 100644
--- a/nexus-am/am/arch/x86-nemu/src/devices/input.c
+++ b/nexus-am/am/arch/x86-nemu/src/devices/input.c
@@ -3,11 +3,15 @@
 #include <amdev.h>
 
 size_t input_read(uintptr_t reg, void *buf, size_t size) {
+  const uint32_t I8042_DATA_PORT = 0x60;
   switch (reg) {
     case _DEVREG_INPUT_KBD: {
       _KbdReg *kbd = (_KbdReg *)buf;
-      kbd->keydown = 0;
-      kbd->keycode = _KEY_NONE;
+      uint32_t press = inl(I8042_DATA_PORT);
+      kbd->keycode = press;
+      if(press != _KEY_NONE){
+          kbd->keydown = !(kbd->keydown);
+      }
       return sizeof(_KbdReg);
     }
   }
diff --git a/nexus-am/am/arch/x86-nemu/src/devices/video.c b/nexus-am/am/arch/x86-nemu/src/devices/video.c
index f56057286afd174c6f843bec4c7418f27da7110f..00cb3ab36ee163a673c9df420ddff6f4203e97f6 100644
--- a/nexus-am/am/arch/x86-nemu/src/devices/video.c
+++ b/nexus-am/am/arch/x86-nemu/src/devices/video.c
@@ -6,11 +6,13 @@
 static uint32_t* const fb __attribute__((used)) = (uint32_t *)0x40000;
 
 size_t video_read(uintptr_t reg, void *buf, size_t size) {
+  const uint32_t SCREEN_PORT = 0x100;
   switch (reg) {
     case _DEVREG_VIDEO_INFO: {
       _VideoInfoReg *info = (_VideoInfoReg *)buf;
-      info->width = 0;
-      info->height = 0;
+      uint32_t screen = inl(SCREEN_PORT);
+      info->width = screen >> 16;
+      info->height = screen << 16 >> 16;
       return sizeof(_VideoInfoReg);
     }
   }
@@ -21,7 +23,13 @@ size_t video_write(uintptr_t reg, void *buf, size_t size) {
   switch (reg) {
     case _DEVREG_VIDEO_FBCTL: {
       _FBCtlReg *ctl = (_FBCtlReg *)buf;
-
+int i;
+int size = screen_width() * screen_height();
+for (i = 0; i < size; i ++) fb[i] = i;
+//      for(int i = 0; i < ctl->h; ++i)
+//      {
+//        memcpy(fb+(ctl->y+i)*screen_width()+ctl->x,ctl->pixels+i*ctl->w,ctl->w*4);
+//      }
       if (ctl->sync) {
         // do nothing, hardware syncs.
       }