学汇编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