`
qdujunjie
  • 浏览: 108717 次
  • 性别: Icon_minigender_1
  • 来自: Mars
社区版块
存档分类
最新评论

汇编语言32位控制台读取用户输入字符程序代码分析(17)

阅读更多

 

 

来自于《Intel汇编语言程序设计》(第四版)第11章---------32位windows编程。

 

 

所谓控制台,就是我们平常在使用XP系统时,在运行框输入CMD之后出现的那个黑色画面,他看起来与DOS系统很相似,但是两者却完全不同。

32位控制台程序运行在保护模式下,而DOS却运行在实模式下。

另外两者使用的函数库也完全不同,Win32控制台程序使用的就是windows下的那些API,而DOS系统使用的却是BIOS和MS-DOS中断。

 

每个win32控制台程序有一个输入缓冲区还有一个或多个屏幕缓冲区,输入缓冲区我们可以看做一个输入流,里面包含了一个输入动作记录的队列,每个输入动作(键盘,鼠标)都会在输入缓冲区中产生一个记录。

 

现在我们来看一下这个程序,它读取用户输入的字符:

 

 

TITLE Read From the Console                      ( ReadConsole.asm )

 

; This program reads a line of input from standard input.

 

INCLUDE Irvine32.inc

 

BufSize = 80

 

.data

buffer BYTE BuffSize DUP(?),0,0

stdInHandle DWORD ?

bytesRead DWORD ?

 

.code

main PROC

      ; Get handle to standard input

      INVOKE GetStdHandle , STD_INPUT_HANDLE

      mov stdInHandle , eax

 

      ; Wait for user input

      INVOKE ReadConsole , stdInHandle , ADDR buffer,

                   BufSize - 2 , ADDR bytesRead , 0

      ; Display the buffer

      mov esi , OFFSET buffer

      mov ecx,16                          ; 16 bytes

      mov ebx , TYPE buffer

      call DumpMem

 

      exit

main ENDP

END main

 

 

我们先回顾一下win32控制台程序相关的内容。

 

如果我们要对控制台进行操作,我们需要使用控制台函数,而几乎每个控制台函数都需要一个32位无符号整数类型的句柄来唯一确定一个对象,句柄的类型如下:

 

STD_INPUT_HANDLE             ; 标准输入句柄

STD_OUTPUT_HANDLE          ; 标准输出句柄

STD_ERROR_HANDLE            ; 标准错误输出句柄

 

要想得到一个句柄,我们可以使用GetStdHandle函数,函数原型为:

 

GetStdHandle PROTO

 nStdHandle : DWORD           ; 句柄的类型

 

例如,我们可以使用如下方法得到句柄,并将句柄值保存起来:

 

.data

inputHandle DWORD ?

.code

          INVOKE GetStdHandle , STD_INPUT_HANDLE

          mov inputHandle , eax

 

 

而在本程序中,我们用到了一个ReadConsole函数,它用于将一个文本输入读取到缓冲区中,函数原型如下:

 

ReadConsole PROTO ,

           handle : DWORD                    ; 输入句柄

           pBuffer : PTR BYTE,                ; 缓冲区地址指针

           maxBytes : DWORD,              ; 要读取的字符串数量

           pBytesRead : PTR DWORD,    ; 指向返回实际读取量大小的指针

           notUsed: DWORD                  ; (保留)

 

 

 

程序其实非常简单:

 

 

      ; Get handle to standard input

      INVOKE GetStdHandle , STD_INPUT_HANDLE             ; 首先调用GetStdHandle 获得一个句柄

      mov stdInHandle , eax                                               ; 将句柄保存到变量stdInHandle 中

 

      ; Wait for user input

      INVOKE ReadConsole , stdInHandle , ADDR buffer,    ;这里为ReadConsole传递参数,其中BufSize - 2是因为我们要接受一个回车,它占用了 0Dh 和 0Ah 两个字节

                   BufSize - 2 , ADDR bytesRead , 0

      ; Display the buffer

      mov esi , OFFSET buffer

      mov ecx,16                          ; 我们决定Dump出16个字节长度

      mov ebx , TYPE buffer

      call DumpMem                      ; Dump

 

当我们在控制台输入abcdefg之后的结果是:

 

61  62  63  64  65  66  67 0D  0A  00  00  00  00  00  00  00

 

可以看到缓冲区中的数据一共为9个,包括abcdefg和最后的用户按下回车键所产生的换行符和回车符。这时ReadConsole 函数的返回值pBytesRead中保存的也是9 。

 

 

 

下面我们来看单个字符的输入。

 

在控制台下输入单个字符与之前的程序有点不同,原书告诉我们控制台输入单字符要用以下步骤:

 

 

1.使用GetConsoleMode函数获取控制台的当前模式,将其暂时保存到一个变量中

2.使用GetConsoleMode来改变控制台的输入模式。

3.用ReadConsole函数读取一个字符

4.用SetConsoleMode函数将原先的模式恢复回去

 

其中GetConsoleMode和SetConsoleMode函数的原型如下:

 

GetConsoleMode PROTO,

      hConsoleHandle : DWORD          ; 输入或者输出句柄

      lpMode : PTR DWORD                  ; 一个双字变量指针

 

SetConsoleMode PROTO,

      hConsoleHandle : DWORD          ; 控制台句柄

      dwMode : DWORD                       ; 控制台模式标志位

 

 

然后是读取单个从键盘输入的字符的程序如下:

 

.data

saveFlags DWORD ?                ; back up of flags

.code

; Get & save the current console input mode flags

INVOKE GetConsoleMode,

       consoleInHandle,

       ADDR saveFlags

 

; Clear all console flags

INVOKE SetConsoleMode,

         consoleInHandle,

         0                                      ; new flag values

 

; Read a single character from input

INVOKE ReadConsole,

         consoleInHandle,            ; console input handle

         ADDR buffer,                   ; pointer to buffer

         1,                                    ; max characters to read

         ADDR bytesRead,0          ; return value

 

; Restore the previous flags state

INVOKE SetConsoleMode,

         consoleInHandle,

         saveFlags

 

 

结束。

分享到:
评论

相关推荐

    汇编语言判断三角形

    当敲下回车后,子程读取字符结束,将进行三次判断三角形两边之和是否大于第三边。然后根据是否能构成三角形输出“Y”或者“N”。子程的最后恢复现场,通用寄存器的值依次出栈。程序结束。 程序运行结果如下图1所示,...

    C#微软培训资料

    18.2 在 C #代码中调用 C++和 VB 编写的组件 .240 18.3 版 本 控 制 .249 18.4 代 码 优 化 .252 18.5 小 结 .254 第五部分 附 录 .255 附录 A 关 键 字.255 附录 B 错 误 码.256 附录 C .Net 名字空间...

    JAVA上百实例源码以及开源项目

    2个目标文件,FTP的目标是:(1)提高文件的共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户...

    JAVA上百实例源码以及开源项目源代码

    2个目标文件,FTP的目标是:(1)提高文件的共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户...

    ARM_Linux启动分析.pdf

    提取并分析核心启动参数(从环境变量中读取参数,设置相应标志位等待处理,(parse_options()) 控制台初始化(为输出信息而先于PCI初始化,console_init()) 剖析器数据结构初始化(prof_buffer和prof_len变量) ...

    网管教程 从入门到精通软件篇.txt

    ASM:汇编语言源文件,Pro/E装配文件 ASP:动态网页文件;ProComm Plus安装与连接脚本文件;Astound介绍文件 AST:Astound多媒体文件;ClarisWorks“助手”文件 Axx:ARJ压缩文件的分包序号文件,用于将一个大...

    易语言程序免安装版下载

     支持静态链接其它编程语言(如C/C++、汇编等)编译生成的静态库(.LIB或.OBJ),但仅限于COFF格式,支持cdecl和stdcall两种函数调用约定。  使用说明如下:函数声明和调用方法与DLL命令一致;“库文件名”以.lib...

    Visual.Basic.2010.&.NET4.高级编程(第6版)-文字版.pdf

    9.4 xml流样式分析程序 348 9.4.1 写入xml流 349 9.4.2 读取xml流 352 9.4.3 文档对象模型(dom) 360 9.5 xslt转换 364 9.5.1 使用xslt转换不同的xml标准 367 9.5.2 system.xml.xsl中定义的其他类和接口 ...

    linux内核 0.11版本源码 带中文注释

    #define __LIBRARY__ // 定义该变量是为了包括定义在unistd.h 中的内嵌汇编代码等信息。 #include <unistd.h> // *.h 头文件所在的默认目录是include/,则在代码中就不用明确指明位置。 // 如果不是UNIX 的标准...

    1345个易语言模块

    24位转单色位图模块.ec 32张发牌.ec 3D引擎支持库-eOgre.ec 69msn.ec ACCESS 到高级表格.ec Access操作.ec Access数据库压缩修复新建.ec ACCSEE记录显示到超级列表框模块.ec ACSII 加解密模块2.0.ec AD.ec ADO方式...

    1350多个精品易语言模块

    24位转单色位图模块.ec 32张发牌.ec 3D引擎支持库-eOgre.ec 69msn.ec ACCESS 到高级表格.ec Access操作.ec Access数据库压缩修复新建.ec ACCSEE记录显示到超级列表框模块.ec ACSII 加解密模块2.0.ec AD.ec ADO方式...

Global site tag (gtag.js) - Google Analytics