标题:学汇编3个多月,终于可以写些像样的程序了,谁可以帮忙写个显示标志位的程序 ...
只看楼主
爱末流
Rank: 2
等 级:论坛游民
帖 子:101
专家分:16
注 册:2011-6-3
结帖率:100%
已结贴  问题点数:10 回复次数:10 
学汇编3个多月,终于可以写些像样的程序了,谁可以帮忙写个显示标志位的程序

学汇编3个多月,终于可以写些像样的程序了...该小程序用来显示32位通用寄存器,包含EIP指令指针寄存器
:显示结果
EAX=004010E3  EBX=00FF1111  ECX=00FFFFFF  EDX=0099922F
ESI=09999999  EDI=0099922F  EBP=0012FFB0  ESP=0012FF9C
EIP=004010E3
OF=0  DF=0  IF=1  TF=0  SF=0  ZF=0  AF=1  PE=0  CF=0


以下是源码,花了6个小时写的哦, 用OD调试很痛苦的,哈哈  

谁可以帮忙写个显示控制标志和状态标志位的的过程,我自己写的觉得不太好。


;funs.inc 头文件
.386
.model flat,stdcall
;必要头文件
include windows.inc
include user32.inc
include kernel32.inc
;导入库文件
includelib user32.lib
includelib kernel32.lib
;函数原型声明
Msg_Out PROTO p_Straddr:dword
Read_Console PROTO in_buffer:dword,buffer_size:dword
Console_Error PROTO
Display_Regs PROTO ptr_r:dword,p_regs:dword,r_size:dword
EFlags PROTO p_Flag:dword



主模块.asm
;编程练习-显示通用寄存器和标志位
include funs.inc
public str_EFLAGS          ;声明全局作用域,允许所有外部模块访问
.data
str_msg byte "-"
buffer  byte ?
str_EAX byte "EAX=00000000  "
str_EBX byte "EBX=00000000  "
str_ECX byte "ECX=00000000  "
str_EDX byte "EDX=00000000",13,10      ;每行长度要相同
str_ESI byte "ESI=00000000  "
str_EDI byte "EDI=00000000  "
str_EBP byte "EBP=00000000  "
str_ESP byte "ESP=00000000",13,10      ;每行长度要相同
str_EIP byte "EIP=00000000",13,10
str_EFLAGS byte "OF=0  DF=0  IF=0  TF=0  SF=0  ZF=0  AF=0  PE=0  CF=0",0    ;为6的倍数来填充各个字符位
out_size = $ - str_EAX
display_reg dword ?
stdHandle dword ?
reallbyte dword ?
.code
main proc
       invoke Msg_Out,addr str_msg                         ;提示输出"-"
       invoke Read_Console,addr buffer,lengthof buffer     ;读取用户输入
       invoke Display_Regs,addr buffer,addr str_EAX,out_size ;进行输出32位通用寄存器,包含EIP寄存器
       invoke ExitProcess,0                                  ;退出程序
       ret
main endp
end main





;DisplayRegs.asm文件模块,核心处理


include funs.inc     ;
extern str_EFLAGS:byte   ;说明该数组是从外部模块定义的
.data
error byte "the commamd error."
.code
call_null proc              ;该过程是call调用的,不自动维护push ebp mov ebp,esp
          mov eax,dword ptr [ebp-14h]
      ret
call_null endp
;负责用于输入不是r字符的时候输出错误"the commamd error."
Console_Error proc
               LOCAL reallbyte:dword
               LOCAL stdHandle:dword
           invoke GetStdHandle,STD_OUTPUT_HANDLE
               mov stdHandle,eax
               invoke WriteConsole,stdHandle,addr error,lengthof error,addr reallbyte,0
           ret
Console_Error endp

;输出提示“-”
Msg_Out   proc p_Straddr:dword
          LOCAL stdHandle:dword
          LOCAL reallbyte:dword
          invoke GetStdHandle,STD_OUTPUT_HANDLE
          mov stdHandle,eax
          invoke WriteConsole,stdHandle,p_Straddr,1,addr reallbyte,0
          ret
Msg_Out endp

;读取用户输入函数
Read_Console proc in_buffer:dword,buffer_size:dword
          LOCAL stdHandle:dword
          LOCAL reallbyte:dword
          invoke GetStdHandle,STD_INPUT_HANDLE
          mov stdHandle,eax
          invoke ReadConsole,stdHandle,in_buffer,buffer_size,addr reallbyte,0
      ret
Read_Console endp


;核心处理代码 显示各个通用寄存器的值(包含了EIP指令指针寄存器)
Display_Regs proc ptr_r:dword,p_regs:dword,r_size:dword
             LOCAL display_reg:dword    ;声明一些局部变量
             LOCAL stdHandle:dword      
             LOCAL reallbyte:dword
             LOCAL loop_val:dword
             mov esi,ptr_r
            
             cmp byte ptr [esi],"r"   ;是否输入:r?
             jne err                  ;不等于r? 跳转显示错误信息,然后结束程序
             mov eax,0123456h         ;要显示假设的数据,如果想动态跟踪通用寄存器,只需要将该假设的寄存器数据去掉即可
             mov ebx,0ff1111h         
             mov ecx,0ffffffh
             mov edx,0f90000h
             mov esi,9999999h
             mov edi,099922fh
             ;反向压入(因为后面代码进行从eax开始弹出堆栈来处理的),利用堆栈存放要输出的寄存器
             call call_null           ;调用空过程
             mov display_reg,eax      ;eax=EIP指令指针值
             push display_reg         ;eip指令指针压入栈
             mov display_reg,esp      ;防止esp堆栈指针被破坏
             push display_reg         ;将esp指针压入堆栈
             mov display_reg,ebp      ;防止ebp堆栈指针被破坏
             push display_reg         ;将ebp基址指针压入堆栈
             ;======================================================================
             push edi                 ;将假设的寄存器数据全部压入堆栈
             push esi                 
             push edi
             push ecx
             push ebx
             push eax
             ;======================================================================
             mov ecx,9            ;外层循环9次,因为有9个寄存器要进行输出
             mov ebx,p_regs       ;将二维数组首地址传给ebx,用ebx定位 行
             mov esi,4            ;esi定位二维数组列
            
;1外层循环 =
L1:          pop eax              ;正向处理从eax开始,第二个弹出ebx寄存器,以此类推
             mov loop_val,ecx     ;必须保存外层循环计数
             mov ecx,8            ;内层循环也要8次,一个32位寄存器需要每次移动一个16进制位到低位进行处理输出 32 / 4 = 8         
;2内层循环=         
L2:          rol eax,4            ;循环左移:向左移动4位,就是移动一个16进制位,将最高的16进制位移入最低位中 循环左移 不丢失eax的各个位。
             mov dl,al            ;为了不破坏原来eax的数据低位,则必须要传送给dl
             and dl,0fh           ;高4位为0
             cmp dl,9             ;大于:9 ?
             ja cov_a_f           ;大于跳转
             add dl,30h           ;不大于进行数字的处理转换
             mov byte ptr [ebx+esi],dl
             inc esi              ;定位二维数组的下个列
             jmp L_exit           ;跳过cov_a_f
                          
cov_a_f:     add dl,37h           ;处理A-F字符的输出
             mov byte ptr [ebx+esi],dl
             inc esi        
L_exit:      loop L2              ;内层循环
;2内层循环=
             mov esi,4            ;重新定位
             add ebx,14           ;定位二维数组的下一行
             mov ecx,loop_val     ;取得内层循环计数
             loop L1              ;外层循环
;1外层循环=
             invoke EFlags,addr str_EFLAGS
             ;进行输出全部通用寄存器
             invoke GetStdHandle,STD_OUTPUT_HANDLE             ;获得标准输出句柄
             mov stdHandle,eax
             invoke WriteConsole,stdHandle,p_regs,r_size,addr reallbyte,0
             jmp exit
err:         invoke Console_Error                ;输出错误信息
exit:        ret
Display_Regs endp

;输出控制和状态标志位
EFlags proc p_Flag:dword
        pushfd                          ;压入32位标志寄存器
    pop eax                         ;弹出32位标志寄存器
    and ax,0000111111010101b        ;将一些没有用到的标志位清0
    mov ecx,16                      ;循环16次
    mov edi,p_Flag
    add edi,3                       ;从3的首地址开始
    xor bl,bl
    xor dl,dl
    ;过滤一些不处理的标志位
L1:     cmp dl ,4         ;跳过ax的前3位,从第4才开始处理
        jb nop_           ;小于4跳转
        cmp dl ,10        ;过滤第10位
        jz nop_
        cmp dl ,12        ;过滤第12位
        jz nop_
        cmp dl ,14        ;过滤第14位
        jz nop_
        
        shl ax,1          ;都不是过滤位,则进行处理
        adc bl,30h
        mov byte ptr [edi],bl  ;第一个则从3的位置开始填充 从0开始数的
        mov bl,0
        add edi,6              ;第二个开始以6的倍数填充字节数组各个0位置处
        inc dl                 ;加1,用于判断是否到了过滤位
        jmp nop_2              ;跳转下一轮循环
nop_:   inc dl                 ;累加跳过的位
        shl ax,1
nop_2:  loop L1
    ret
EFlags endp
end

搜索更多相关主题的帖子: 寄存器 标志 
2012-08-17 00:32
爱末流
Rank: 2
等 级:论坛游民
帖 子:101
专家分:16
注 册:2011-6-3
得分:0 
;输出控制和状态标志位过程 没有调试过,不知道是否正确
2012-08-17 00:34
Agdmeg
Rank: 4
来 自:四川成都
等 级:业余侠客
威 望:3
帖 子:101
专家分:201
注 册:2011-8-9
得分:3 
显示通用寄存器和标志位,没必要弄这么复杂吧
2012-08-17 02:45
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
得分:3 
膜拜成长的牛。。。

梅尚程荀
马谭杨奚







                                                       
2012-08-17 09:17
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
得分:3 
这贴有分抓紧散了罢
2012-08-17 10:29
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
得分:0 
程序代码:

.386
.model flat, stdcall
option casemap :none

include windows.inc
include user32.inc
include kernel32.inc
include masm32.inc
include libc.inc

includelib user32.lib
includelib kernel32.lib
includelib masm32.lib
includelib msvcrt.lib
include macro.asm

.data?
    buffer    db 100 dup(?)
   
.CODE
START:
   
    invoke printf,CTXT('EAX=%08x',0dh,0ah), eax
    invoke printf,CTXT('EBX=%08x',0dh,0ah), ebx
    invoke printf,CTXT('ECX=%08x',0dh,0ah), ecx
    invoke printf,CTXT('EDX=%08x',0dh,0ah), edx
OPS:   
    call @F
OPE:
@@:
    pop eax
    sub eax,(OPE-OPS)
    invoke printf,CTXT('EIP=%08x',0dh,0ah), eax
   
    ;暂停显示,回车键关闭
    invoke StdIn,addr buffer,sizeof buffer
    invoke ExitProcess,0
   
end START



最简单的写法是用C的运行时库
2012-08-17 10:44
爱末流
Rank: 2
等 级:论坛游民
帖 子:101
专家分:16
注 册:2011-6-3
得分:0 
回复 3楼 Agdmeg
我第一次写,利用堆栈来保存寄存器,还用rol循环移位实现的。
2012-08-17 11:09
爱末流
Rank: 2
等 级:论坛游民
帖 子:101
专家分:16
注 册:2011-6-3
得分:0 
回复 6楼 zklhp
没有用过C的函数写过
2012-08-17 11:09
水哥
Rank: 5Rank: 5
等 级:贵宾
威 望:15
帖 子:65
专家分:111
注 册:2012-8-11
得分:0 
可以在任何点把线程挂起,用GetThreadContext得到所有寄存器和标志寄存器的值
iDr0 dd ?
iDr1 dd ?
iDr2 dd ?
iDr3 dd ?
iDr6 dd ?
iDr7 dd ?
regGs dd ?
regFs dd ?
regEs dd ?
regDs dd ?
regEdi dd ?
regEsi dd ?
regEbx dd ?
regEdx dd ?
regEcx dd ?
regEax dd ?
regEbp dd ?
regEip dd ?
regCs dd ?
regFlag dd ?
regEsp dd ?
regSs dd ?



2012-08-17 13:31
fawdlstty
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2012-8-25
得分:0 
汇编程序用C库多不好?还是直接用汇编算了,打印一行子直接用StdOut就OK,关于字串自己加个类型转换函数,我觉得这样最好
2012-08-25 18:37



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-379633-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.186516 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved