diff --git a/ChangeLog b/ChangeLog
index ea14d3f0ecb55e3123247c646283bd74e2777504..8d098eaea37429f1b12db4add4614d4f125b2063 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -415,4 +415,5 @@
 	* NSH now supports last exit status $?
 	* NSH now supports if-then[-else]-fi construct
 	* NSH now supports comments beginning with '#'
+	* NSH now supports commands to inspect and modify memory
 
diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html
index fcf807ef7957fd8ab389d2bbc9a8363261bda617..3c4bfe8ac2b83f5901ef9aef51557d4bcf3983d5 100644
--- a/Documentation/NuttX.html
+++ b/Documentation/NuttX.html
@@ -8,7 +8,7 @@
   <tr align="center" bgcolor="#e4e4e4">
     <td>
       <h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
-      <p>Last Updated: August 17, 2008</p>
+      <p>Last Updated: August 19, 2008</p>
     </td>
   </tr>
 </table>
@@ -1049,6 +1049,7 @@ nuttx-0.3.13 2008-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
 	* NSH now supports last exit status $?
 	* NSH now supports if-then[-else]-fi construct
 	* NSH now supports comments beginning with '#'
+	* NSH now supports commands to inspect and modify memory
 
 pascal-0.1.3 2008-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
 
diff --git a/examples/nsh/Makefile b/examples/nsh/Makefile
index 931ba2b16de26a7a111b8b7e237a72cc346eb26d..db2f26677ec578d9cb3b9ab778794d0f27d27cd8 100644
--- a/examples/nsh/Makefile
+++ b/examples/nsh/Makefile
@@ -37,7 +37,7 @@
 -include $(TOPDIR)/Make.defs
 
 ASRCS	= 
-CSRCS	= nsh_main.c nsh_fscmds.c nsh_proccmds.c nsh_envcmds.c
+CSRCS	= nsh_main.c nsh_fscmds.c nsh_proccmds.c nsh_envcmds.c nsh_dbgcmds.c
 
 ifeq ($(CONFIG_NET),y)
 ifneq ($(CONFIG_NSOCKET_DESCRIPTORS),0)
diff --git a/examples/nsh/nsh.h b/examples/nsh/nsh.h
index 57c75e1bc0c5c24cbf1a4fedd002187f1c0bb952..33f6d3d4d45e7c690d8a1262f2022593cd119da6 100644
--- a/examples/nsh/nsh.h
+++ b/examples/nsh/nsh.h
@@ -182,6 +182,7 @@ typedef int (*cmd_t)(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
 extern const char g_nshprompt[];
 extern const char g_fmtargrequired[];
 extern const char g_fmtarginvalid[];
+extern const char g_fmtargrange[];
 extern const char g_fmtcmdnotfound[];
 extern const char g_fmtcmdnotimpl[];
 extern const char g_fmtnosuch[];
@@ -214,6 +215,9 @@ extern int nsh_telnetmain(int argc, char *argv[]);
 
 extern int cmd_echo(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
 extern int cmd_exec(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+extern int cmd_mb(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+extern int cmd_mh(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+extern int cmd_mw(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
 extern int cmd_ps(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
 
 #if CONFIG_NFILE_DESCRIPTORS > 0
diff --git a/examples/nsh/nsh_dbgcmds.c b/examples/nsh/nsh_dbgcmds.c
new file mode 100644
index 0000000000000000000000000000000000000000..5ae5d658efa4c654fe6caf3687aa3d73013628a2
--- /dev/null
+++ b/examples/nsh/nsh_dbgcmds.c
@@ -0,0 +1,279 @@
+/****************************************************************************
+ * examples/nsh/dbg_proccmds.c
+ *
+ *   Copyright (C) 2008 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "nsh.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct dbgmem_s
+{
+  boolean      dm_write;  /* TRUE: perfrom write operation */
+  void        *dm_addr;   /* Address to access */
+  uint32       dm_value;  /* Value to write */
+  unsigned int dm_count;  /* The number of bytes to access */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mem_parse
+ ****************************************************************************/
+
+int mem_parse(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv,
+              struct dbgmem_s *mem)
+{
+  char *pcvalue = strchr(argv[1], '=');
+  unsigned long lvalue = 0;
+
+  /* Check if we are writing a value */
+
+  if (pcvalue)
+    {
+      *pcvalue = '\0';
+      pcvalue++;
+ 
+      lvalue = (unsigned long)strtol(pcvalue, NULL, 16);
+      if (lvalue > 0xffffffff)
+        {
+          return -EINVAL;
+        }
+
+      mem->dm_write = TRUE;
+      mem->dm_value = (uint32)lvalue;
+    }
+  else
+    {
+      mem->dm_write = FALSE;
+      mem->dm_value = 0;
+    }
+
+  /* Get the address to be accessed */
+
+  mem->dm_addr = (void*)strtol(argv[1], NULL, 16);
+
+  /* Get the number of bytes to access */
+
+  if (argc > 2)
+    {
+      mem->dm_count = (unsigned int)strtol(argv[2], NULL, 16);
+    }
+  else
+    {
+      mem->dm_count = 1;
+    }
+  return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cmd_mb
+ ****************************************************************************/
+
+int cmd_mb(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+  struct dbgmem_s mem;
+  volatile ubyte *ptr;
+  int ret;
+  int i;
+
+  ret = mem_parse(vtbl, argc, argv, &mem);
+  if (ret == 0)
+    {
+      /* Loop for the number of requested bytes */
+
+      for (i = 0, ptr = (volatile ubyte*)mem.dm_addr; i < mem.dm_count; i++, ptr++)
+	{
+	  /* Print the value at the address */
+
+	  nsh_output(vtbl, "  %p = 0x%02x", ptr, *ptr);
+
+	  /* Are we supposed to write a value to this address? */
+
+	  if (mem.dm_write)
+	    {
+	      /* Yes, was the supplied value within range? */
+
+	      if (mem.dm_value > 0x000000ff)
+		{
+		  nsh_output(vtbl, g_fmtargrange, argv[0]);
+		  return ERROR;
+		}
+
+	      /* Write the value and re-read the address so that we print its
+	       * current value (if the address is a process address, then the
+	       * value read might not necessarily be the value written).
+	       */
+
+	      *ptr = (ubyte)mem.dm_value;
+	      nsh_output(vtbl, " -> 0x%02x", *ptr);
+	    }
+
+	  /* Make sure we end it with a newline */
+
+	  nsh_output(vtbl, "\n", *ptr);
+	}
+    }
+  return ret;
+}
+
+/****************************************************************************
+ * Name: cmd_mh
+ ****************************************************************************/
+
+int cmd_mh(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+  struct dbgmem_s mem;
+  volatile uint16 *ptr;
+  int ret;
+  int i;
+
+  ret = mem_parse(vtbl, argc, argv, &mem);
+  if (ret == 0)
+    {
+      /* Loop for the number of requested bytes */
+
+      for (i = 0, ptr = (volatile uint16*)mem.dm_addr; i < mem.dm_count; i += 2, ptr++)
+	{
+	  /* Print the value at the address */
+
+	  nsh_output(vtbl, "  %p = 0x%04x", ptr, *ptr);
+
+	  /* Are we supposed to write a value to this address? */
+
+	  if (mem.dm_write)
+	    {
+	      /* Yes, was the supplied value within range? */
+
+	      if (mem.dm_value > 0x0000ffff)
+		{
+		  nsh_output(vtbl, g_fmtargrange, argv[0]);
+		  return ERROR;
+		}
+
+	      /* Write the value and re-read the address so that we print its
+	       * current value (if the address is a process address, then the
+	       * value read might not necessarily be the value written).
+	       */
+
+	      *ptr = (uint16)mem.dm_value;
+	      nsh_output(vtbl, " -> 0x%04x", *ptr);
+	    }
+
+	  /* Make sure we end it with a newline */
+
+	  nsh_output(vtbl, "\n", *ptr);
+	}
+    }
+  return ret;
+}
+
+/****************************************************************************
+ * Name: cmd_mw
+ ****************************************************************************/
+
+int cmd_mw(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+  struct dbgmem_s mem;
+  volatile uint32 *ptr;
+  int ret;
+  int i;
+
+  ret = mem_parse(vtbl, argc, argv, &mem);
+  if (ret == 0)
+    {
+      /* Loop for the number of requested bytes */
+
+      for (i = 0, ptr = (volatile uint32*)mem.dm_addr; i < mem.dm_count; i += 4, ptr++)
+	{
+	  /* Print the value at the address */
+
+	  nsh_output(vtbl, "  %p = 0x%08x", ptr, *ptr);
+
+	  /* Are we supposed to write a value to this address? */
+
+	  if (mem.dm_write)
+	    {
+	      /* Write the value and re-read the address so that we print its
+	       * current value (if the address is a process address, then the
+	       * value read might not necessarily be the value written).
+	       */
+
+	      *ptr = mem.dm_value;
+	      nsh_output(vtbl, " -> 0x%08x", *ptr);
+	    }
+
+	  /* Make sure we end it with a newline */
+
+	  nsh_output(vtbl, "\n", *ptr);
+	}
+    }
+  return ret;
+}
+
diff --git a/examples/nsh/nsh_main.c b/examples/nsh/nsh_main.c
index ff3398ea114b552eb4d4741488a794a5da4086c4..b7070f43959e0ae96c8a2681e749b68dc9d52014 100644
--- a/examples/nsh/nsh_main.c
+++ b/examples/nsh/nsh_main.c
@@ -107,16 +107,21 @@ static const struct cmdmap_s g_cmdmap[] =
 #if CONFIG_NFILE_DESCRIPTORS > 0
   { "ls",       cmd_ls,       2, 5, "[-lRs] <dir-path>" },
 #endif
+  { "mb",       cmd_mb,       2, 3, "<hex-address>[=<hex-value>][ <hex-byte-count>]" },
 #if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0
   { "mkdir",    cmd_mkdir,    2, 2, "<path>" },
 #ifdef CONFIG_FS_FAT
   { "mkfatfs",  cmd_mkfatfs,  2, 2, "<path>" },
 #endif
   { "mkfifo",   cmd_mkfifo,   2, 2, "<path>" },
+#endif
+  { "mh",       cmd_mh,       2, 3, "<hex-address>[=<hex-value>][ <hex-byte-count>]" },
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0
 #ifdef CONFIG_FS_FAT /* Need at least one filesytem in configuration */
   { "mount",    cmd_mount,    4, 5, "-t <fstype> <block-device> <dir-path>" },
 #endif
 #endif
+  { "mw",       cmd_mw,       2, 3, "<hex-address>[=<hex-value>][ <hex-byte-count>]" },
   { "ps",       cmd_ps,       1, 1, NULL },
 #ifndef CONFIG_DISABLE_ENVIRON
   { "set",      cmd_set,      3, 3, "<name> <value>" },
@@ -152,6 +157,7 @@ static const struct cmdmap_s g_cmdmap[] =
 const char g_nshprompt[]         = "nsh> ";
 const char g_fmtargrequired[]    = "nsh: %s: missing required argument(s)\n";
 const char g_fmtarginvalid[]     = "nsh: %s: argument invalid\n";
+const char g_fmtargrange[]       = "nsh: %s: value out of range\n";
 const char g_fmtcmdnotfound[]    = "nsh: %s: command not found\n";
 const char g_fmtcmdnotimpl[]     = "nsh: %s: command not implemented\n";
 const char g_fmtnosuch[]         = "nsh: %s: no such %s: %s\n";