首页
社区
课程
招聘
超难!超复杂的汇编语言问题!
发表于: 2007-9-3 14:35 5360

超难!超复杂的汇编语言问题!

2007-9-3 14:35
5360
程序的目的是从控制台读取一个字符串,然后判断它是否为数字字符串
代码如下:
    .486                                ; create 32 bit code
    .model flat, stdcall                ; 32 bit memory model
    option casemap :none                ; case sensitive
    include \masm32\include\windows.inc
    include \masm32\include\masm32.inc
    include \masm32\include\gdi32.inc
    include \masm32\include\user32.inc
    include \masm32\include\kernel32.inc
    include \masm32\include\Comctl32.inc
    include \masm32\include\comdlg32.inc
    include \masm32\include\shell32.inc
    include \masm32\include\oleaut32.inc
    include \masm32\include\msvcrt.inc

    includelib \masm32\lib\masm32.lib
    includelib \masm32\lib\gdi32.lib
    includelib \masm32\lib\user32.lib
    includelib \masm32\lib\kernel32.lib
    includelib \masm32\lib\Comctl32.lib
    includelib \masm32\lib\comdlg32.lib
    includelib \masm32\lib\shell32.lib
    includelib \masm32\lib\oleaut32.lib
    includelib \masm32\lib\msvcrt.lib

    .data?
hStdIn DWORD ?
hStdOut DWORD ?
haveread DWORD ?
num1 db ?
    .data
info1 db "Please enter a valid number!",0

    .code

start:

invoke        GetStdHandle,STD_INPUT_HANDLE
mov        hStdIn,eax
invoke        GetStdHandle,STD_OUTPUT_HANDLE
mov        hStdOut,eax
invoke ReadFile,hStdIn,offset num1,9,offset haveread,NULL
lea esi,num1
push esi
mov eax,haveread
adc esi,eax
inc esi
mov [esi],byte ptr 0
pop esi
call isnumornot
cmp eax,1
je h1
invoke WriteFile,hStdOut,offset info1,28,offset haveread,NULL
ret
h1:
invoke WriteFile,hStdOut,offset num1,9,offset haveread,NULL
invoke ExitProcess,NULL

isnumornot proc
    comehere:
    cmp [esi],byte ptr 0
    je quit1
    cmp [esi],byte ptr '0'
    jb quit2
    cmp [esi],byte ptr '9'
    ja quit2
    inc esi
    jmp comehere
    quit1:
    mov eax,1
    ret
    quit2:
    mov eax,0
    ret
isnumornot endp

  
end start

我详细的描述一下问题,ReadFile函数有一个参数是最大读取数(nNumberOfBytesToRead),在此程序中我设置的为9,这个程序未经修改之前,如果恰好输入9字节长的字符串,就能正确运行,如果小于9的话,得到的结果就是错误的!

后来我发现可以用ReadFile的lpNumberOfBytesRead参数得到已经读取的实际字节数,于是我就想,把实际读取完的下一位(比如读取了6位,则是第7位)置为0,然后再调用isnumornot函数来判断是否为数字字符串,本以为这样就不会出错了,哪知还是不行

然后我又用Ollydbg进行调试,但是调试确发现了一些奇怪的东西
我的输入是1111,按回车后,在Ollydbg中esi的值如图所示

图片


4个1后面的字符代表什么呢?如果是代表ASCII码为0的字符的话,我没有修改程序(即没有考虑把实际读取的下一位置为0)的时候就应该正确运行啊~~!!


我已经彻底晕了,希望各位能帮我解除此疑惑,不胜感激!

[培训]科锐逆向工程师培训第53期2025年7月8日开班!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 200
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
2
再补充一下,在Ollydbg中可以发现,haveread的值比实际输入的长度大2,应该就是后面那两个字符,于是我尝试执行两次dec esi,但是这样反而导致"Please enter a valid number!"无法正常显示```

此程序的功能我已经通过其他办法达到,但我想知道自己为什么错了,希望懂得的一定解答!
2007-9-3 16:23
0
雪    币: 313
活跃值: (440)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
3
估计把回车也读进去了
2007-9-3 21:25
0
雪    币: 200
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
4
估计得完全正确!这个问题搞了一天我才解决,汗一下!
2007-9-3 22:38
0
雪    币: 796
活跃值: (370)
能力值: ( LV9,RANK:380 )
在线值:
发帖
回帖
粉丝
5
"超难!超复杂"

有点骇人听闻了
2007-9-4 09:14
0
游客
登录 | 注册 方可回帖
返回