标题: 通过大家努力,批处理可告别choice
[打印本页]
作者: wangff
时间: 2008-12-9 11:37
标题: 通过大家努力,批处理可告别choice
改进版在26楼:
大家共同改进!
@echo off
call inc 2>nul
if %errorlevel%==1 (
>inc.src echo ecs:100 B8 00 01 CD 16 B8 00 00 74 02 CD 16 B4 4C CD 21
>>inc.src echo rcx
>>inc.src echo 10
>>inc.src echo w
>>inc.src echo q
debug inc.com < inc.src 2>nul 1>nul
del inc.src
)
:loop
inc
if not %errorlevel%==0 (
echo %errorlevel%
if %errorlevel%==81 goto :eof ::q or Q exit
if %errorlevel%==113 goto :eof
)
ping -n 2 127.1>nul
goto loop
[
Last edited by wangff on 2008-12-11 at 10:34 ]
作者: wangff
时间: 2008-12-9 16:09
@echo off
call inc 2>nul
if %errorlevel%==1 ( ::inc 不存在则创建
>inc.src echo ecs:100 A0 5D 00 3C 20 75 09 B4 01 CD 16 B8 00 00 74 02 CD 16 B4 4C CD 21
>>inc.src echo rcx
>>inc.src echo 16
>>inc.src echo w
>>inc.src echo q
debug inc.com < inc.src 2>nul 1>nul
del inc.src
)
set/p =input:<nul
inc i ::有参数(任意)等待输入一个字符,通过errorlevel返回
echo %errorlevel%
:loop
inc ::无参数检测是否有按键 无:errorlevel=0 有errorlevel=键值 可用干运行中动态检测按键
echo %errorlevel%
if not %errorlevel%==0 (
if %errorlevel%==81 goto :eof ::q or Q exit
if %errorlevel%==113 goto :eof
)
ping -n 2 127.1>nul
goto loop
[
Last edited by wangff on 2008-12-10 at 21:35 ]
作者: s11ss
时间: 2008-12-9 19:33
wangff兄可不可以讲解下int 16的1号功能是怎么用的?
作者: wangff
时间: 2008-12-9 20:58
键盘服务(Keyboard Service——INT 16H)
作者:佚名 出处:中国自学编程网收集整理 发布日期:2007-09-27
00H、10H —从键盘读入字符03H —设置重复率
01H、11H —读取键盘状态04H —设置键盘点击
02H, 12H —读取键盘标志05H —字符及其扫描码进栈
(1)、功能00H和10H
功能描述:从键盘读入字符
入口参数:AH=00H——读键盘
=10H——读扩展键盘,可根据0000:0496H单元的内容判断:扩展键盘是否有效
出口参数:AH=键盘的扫描码
AL=字符的ASCII码
(2)、功能01H和11H
功能描述:读取键盘状态
入口参数:AH=01H——检查普通键盘
=11H——检查扩展键盘
出口参数:ZF=1——无字符输入,否则,AH=键盘的扫描码,AL=ASCII码。
(3)、功能02H和12H
功能描述:读取键盘标志
入口参数:AH=02H——普通键盘的移位标志
=12H——扩展键盘的移位标志
出口参数:AL=键盘标志(02H和12H都有效),其各位之值为1时的含义如下: 位7—INS开状态位3—ALT键按下
位6—CAPS LOCK开状态位2—CTRL键按下
位5—NUM LOCK开状态位1—左SHIFT键按下
位4—SCROLL LOCK开状态位0—右SHIFT键按下
AH=扩展键盘的标志(12H有效),其各位之值为1时的含义如下:
位7—SysReq键按下位3—右ALT键按下
位6—CAPS LOCK键按下位2—右CTRL键按下
位5—NUM LOCK键按下位1—左ALT键按下
位4—SCROLL键按下位0—左CTRL键按下
(4)、功能03H
功能描述:设置重复率
入口参数:AH=03H 对于PC/AT和PS/2:AL=05H
BH=重复延迟
BL=重复率
对于PCjr:AL=00H——装入缺省的速率和延迟
=01H——增加初始延迟
=02H——重复频率降低一半
=03H——增加延迟和降低一半重复频率
=04H——关闭键盘重复功能
出口参数:无
(5)、功能04H
功能描述:设置键盘点击
入口参数:AH=04H AL=00H——关闭键盘点击功能
=01H——打开键盘点击功能
出口参数:无
(6)、功能05H
功能描述:字符及其扫描码进栈
入口参数:AH=05H
CH=字符的描述码
CL=字符的ASCII码
出口参数:CF=1——操作成功,AL=00H,否则,AL=01H
作者: s11ss
时间: 2008-12-9 21:04
不好意思,这不算讲解吧?至少给一两个例子说明下嘛:)
作者: wangff
时间: 2008-12-9 21:28
(2)、功能01H
功能描述:读取键盘状态
入口参数:AH=01H——检查普通键盘
出口参数:ZF=1——无字符输入,否则,AH=键盘的扫描码,AL=ASCII码。
mov ah,1 ;检测是否按键
int 16h
mov ax,0 ;ah=0 读键,清al
jz ret ;zf=1 无按键返回0
int 16h ;有按键,读出的ASCII在al
ret:
mov ah,4ch ;将al返回给 errorleve
int 21h
不知说清楚否?打字很慢,请谅解.
作者: s11ss
时间: 2008-12-9 22:03
mov ah,0
int 16
上面两句不就是读输入么,还要1号功能干什么?
作者: wangff
时间: 2008-12-9 22:15
Quote: |
Originally posted by s11ss at 2008-12-9 22:03:
mov ah,0
int 16
上面两句不就是读输入么,还要1号功能干什么? |
|
ah=0: 是等待输入 ah=1: 只检测,不读取(还在键盘缓冲中),如有输入还必须用ah=0读出
[
Last edited by wangff on 2008-12-9 at 22:17 ]
作者: s11ss
时间: 2008-12-9 22:20
Quote: |
Originally posted by wangff at 2008-12-9 10:15 PM:
ah=0: 是等待输入 ah=1: 只检测,不读取(还在键盘缓冲中),如有输入还必须用ah=0读出
[ Last edited by wangff on 2008-12-9 at 22:17 ] |
|
C:\>debug
-a
0B22:0100 mov ah,0
0B22:0102 int 16
0B22:0104
-t
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0B22 ES=0B22 SS=0B22 CS=0B22 IP=0102 NV UP EI PL NZ NA PO NC
0B22:0102 CD16 INT 16
-p
(此处输入的是a)
AX=1E
61 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0B22 ES=0B22 SS=0B22 CS=0B22 IP=0104 NV UP EI PL NZ NA PO NC
0B22:0104 381C CMP [SI],BL DS:0000=CD
-
我还是觉得用0号就行了
[
Last edited by s11ss on 2008-12-9 at 22:22 ]
作者: wangff
时间: 2008-12-9 22:36
2楼的例子:
inc i ::有参数(任意)等待输入一个字符,通过errorlevel返回
就只用了ah=0
而:
inc ::无参数检测是否有按键 无:errorlevel=0 有errorlevel=键值 可用干运行中动态检测按键
则必须用到 ah=1
作者: s11ss
时间: 2008-12-9 22:48
Quote: |
Originally posted by wangff at 2008-12-9 10:36 PM:
2楼的例子:
inc i ::有参数(任意)等待输入一个字符,通过errorlevel返回
就只用了ah=0
而:
inc ::无参数检测是否有按键 无:errorlevel=0 有errorlevel=键值 可用干运行中动态检测按键
则必须用到 ah=1 |
|
无按键是直接回车的情况么?如果只用0号的话,al是0d啊
作者: wangff
时间: 2008-12-9 23:02
@echo off
:loop
for /f "tokens=*" %%a in ('ping -n 1 127.1 ^| findstr /i "Request Reply"') do echo.%%a
inc ::无参数检测是否有按键 无:errorlevel=0 有errorlevel=键值 可用干运行中动态检测按键
if not %errorlevel%==0 (
if %errorlevel%==112 pause ::input p or P pause
if %errorlevel%==90 pause
if %errorlevel%==81 goto :eof ::input q or Q exit
if %errorlevel%==113 goto :eof
)
ping -n 2 127.1>nul
goto loop
这个例子就可说明,只用ah=0做不到这种效果
[
Last edited by wangff on 2008-12-9 at 23:06 ]
作者: s11ss
时间: 2008-12-9 23:30
我慢慢体会吧,有劳了,wangff兄
作者: s11ss
时间: 2008-12-9 23:59
二楼的ecs:100 A0 5D 00 3C 20 75 09 B4 01 CD 16 B8 00 00 74 02 CD 16 B4 4C CD 21 CD 21 CD 21中,3次int 21,何故?
作者: wangff
时间: 2008-12-10 08:22
Quote: |
Originally posted by s11ss at 2008-12-9 23:59:
二楼的ecs:100 A0 5D 00 3C 20 75 09 B4 01 CD 16 B8 00 00 74 02 CD 16 B4 4C CD 21 CD 21 CD 21中,3次int 21,何故? |
|
谢谢s11ss的细心,是从debug考下多余的,被长度16h约束没存到inc.com中不影响使用,已修改.
作者: wangff
时间: 2008-12-10 08:32
Quote: |
Originally posted by s11ss at 2008-12-9 22:48:
无按键是直接回车的情况么?如果只用0号的话,al是0d啊 |
|
无按键就是沒动键盘.
作者: wxcute
时间: 2008-12-10 14:00
真的很强,像我等不懂汇编的就只能望洋兴叹了。
作者: 本是
时间: 2008-12-10 14:31
上面的程序中mov ax,0长3字节,改mov ah,0或xor ah,ah或sub ah,ah就能少1个字节。
其实,此类程序最短的只要8字节。
DEBUG
a
mov ah,0
int 16h
mov ah,4Ch
int 21h
rcx
8
nkeycode.com
w
q
作者: s11ss
时间: 2008-12-10 14:55
Quote: |
Originally posted by 本是 at 2008-12-10 02:31 PM:
上面的程序中mov ax,0长3字节,改mov ah,0或xor ah,ah或sub ah,ah就能少1个字节。
其实,此类程序最短的只要8字节。
DEBUG
a
mov ah,0
int 16h
mov ah,4Ch
... |
|
我的意思就是不用int 16h的1号功能,看来还是行的~
其实好像可以不写com,直接用debug调用:)
作者: wangff
时间: 2008-12-10 15:32
Quote: |
Originally posted by 本是 at 2008-12-10 14:31:
上面的程序中mov ax,0长3字节,改mov ah,0或xor ah,ah或sub ah,ah就能少1个字节。
其实,此类程序最短的只要8字节。
DEBUG
a
mov ah,0
int 16h
mov ah,4Ch
... |
|
还是误解了,试一下12楼的例子就会发现与上面的程序不一样之处
作者: wangff
时间: 2008-12-10 15:45
@echo off
call inc 2>nul
if %errorlevel%==1 (
>inc.src echo ecs:100 B8 00 01 CD 16 B8 00 00 74 02 CD 16 B4 4C CD 21
>>inc.src echo rcx
>>inc.src echo 10
>>inc.src echo w
>>inc.src echo q
debug inc.com < inc.src 2>nul 1>nul
del inc.src
)
:loop
inc
echo %errorlevel%
if not %errorlevel%==0 (
if %errorlevel%==81 goto :eof ::q or Q exit
if %errorlevel%==113 goto :eof
)
ping -n 2 127.1>nul
goto loop
或试一下这个,没输入时循环一直在跑.而不是等输入.
本帖主要就是用int 16h的ah=1,(也就是它与choice的主耍区别)没说清楚就毫无意义.
也许是我的表达能力不行,站内高手云云,有谁能邦我说明白?
[
Last edited by wangff on 2008-12-10 at 17:51 ]
作者: wangff
时间: 2008-12-10 17:47
Quote: |
Originally posted by s11ss at 2008-12-10 14:55:
我的意思就是不用int 16h的1号功能,看来还是行的~
其实好像可以不写com,直接用debug调用:) |
|
不用com也行,但要有脚本 如 c.txt
a
MOV AX,0100
INT 16
MOV AX,0000
JZ 010C
INT 16
MOV AH,4C
INT 21
g
q
p代码:
@echo off
:loop
debug <c.txt>nul
echo %errorlevel%
if not %errorlevel%==0 (
if %errorlevel%==81 goto :eof ::q or Q exit
if %errorlevel%==113 goto :eof
)
ping -n 2 127.1>nul
goto loop
效果一样.
[
Last edited by wangff on 2008-12-10 at 17:52 ]
作者: wangff
时间: 2008-12-10 18:56
只用int 16h功能ah=0的例子:
脚本: a.txt
a
mov ah,0
int 16
mov ah,4C
int 21
g
q
p代码:
@echo off
:loop
debug <a.txt>nul
echo %errorlevel%
if not %errorlevel%==0 (
if %errorlevel%==81 goto :eof ::q or Q exit
if %errorlevel%==113 goto :eof
)
ping -n 2 127.1>nul
goto loop
作者: s11ss
时间: 2008-12-10 19:07
可以不要临时文件的
goto :main
a
;MOV AX,0100
;INT 16
MOV AX,0000
;JZ 010C
INT 16
MOV AH,4C
INT 21
g
q
:main
@echo off
:loop
debug <"%~f0">nul
echo %errorlevel%
if not %errorlevel%==0 (
if %errorlevel%==81 goto :eof ::q or Q exit
if %errorlevel%==113 goto :eof
)
ping -n 2 127.1>nul
goto loop
作者: zh159
时间: 2008-12-10 21:47
加两行快速清除“goto :main”显示和支持中文显示(XP测试)
Quote: |
......
:main
cls
@echo off
chcp 437|graftabl 936>nul
...... |
|
作者: pyjhhh
时间: 2008-12-10 23:32
好帖子
作者: wangff
时间: 2008-12-11 09:19
2楼可带参数的完善版:
@echo off
goto main
a
MOV AL,[005D]
CMP AL,20
JNZ 0110
MOV AH,01
INT 16
MOV AX,0000
JZ 0112
INT 16
MOV AH,4C
INT 21
g
q
:main
chcp 437|graftabl 936>nul
set/p =input:<nul
::有参数(任意)等待输入一个字符,通过errorlevel返回
debug a.com i<"%~f0">nul 2>nul
echo %errorlevel%
:loop
::无参数检测是否有按键 无:errorlevel=0 有errorlevel=键值 可用干运行中动态检测按键
debug<"%~f0">nul
echo %errorlevel%
if not %errorlevel%==0 (
if %errorlevel%==81 goto :eof ::q or Q exit
if %errorlevel%==113 goto :eof
)
ping -n 2 127.1>nul
goto loop
作者: wangff
时间: 2008-12-11 10:56
自动运行:
@echo off
goto main
a
MOV AL,[005D]
CMP AL,20
JNZ 0110
MOV AH,01
INT 16
MOV AX,0000
JZ 0112
INT 16
MOV AH,4C
INT 21
g
q
:main
chcp 437|graftabl 936>nul
set/p =等待...<nul&set/a n=0
:loop
set/a n+=1
set/p =.%n%<nul
debug<"%~f0">nul
if not %errorlevel%==0 (
if %errorlevel%==81 goto :eof ::q or Q exit
if %errorlevel%==113 goto :eof
)
if %n% gtr 5 goto p1
ping -n 2 127.1>nul
goto loop
:p1
echo.
echo 计时到,自动运行!
pause
作者: Helloworld
时间: 2008-12-11 13:19
兄们的创造能力实在是厉害!
作者: s11ss
时间: 2008-12-11 13:23
告别choice,这么说好像有点牵强,choice功能还是相对强大的说:)
作者: wangff
时间: 2008-12-11 13:33
可否举个例子?
作者: s11ss
时间: 2008-12-11 14:13
Quote: |
Originally posted by wangff at 2008-12-11 01:33 PM:
可否举个例子? |
|
choice /?
作者: wangff
时间: 2008-12-11 14:20
我是这样理解的:
1.关于键盘输入choice不外乎也是用ah=0及ah=1两基本功能来实现的
2.choice再好也不是每套系统都有预装(我的xp就没有)
3.choice功能再強也是固定的,而p只要有了这两基本功能其它的就发挥大家的想象能力,是鱼好还是渔杆好大家都明白
4.告别choice作为一个目标,大家共同努力
[
Last edited by wangff on 2008-12-11 at 15:11 ]
作者: zh159
时间: 2008-12-11 18:19
这样就不用那么多跳转了
...
ping -n 2 127.1>nul
if %n% LEQ 5 goto loop
echo.
echo 计时到,自动运行!
pause
作者: qzwqzw
时间: 2008-12-11 18:33
“是鱼好还是渔杆好大家都明白”
相信真正明白的没有几个
毕竟与鱼相比
鱼竿还需要一汪水和一片饵
如果真要说鱼竿好
那么再问是鱼竿与木棍+线+钩子孰好?
而鱼与红烧鲤鱼孰好?
又该怎么抉择
别忘了debug在cmd是个很麻烦的东西
用起来会有很多潜在的问题(不仅仅是代码页)
作者: wangff
时间: 2008-12-11 19:29
35楼说的有道理,但:
"别忘了debug在cmd是个很麻烦的东西
用起来会有很多潜在的问题(不仅仅是代码页)"
本人确实不知,能否告知一二,如果致命则放弃这种想法.因debug为p嵌入小汇编成为可行,我觉得廷重要的.
[
Last edited by wangff on 2008-12-11 at 19:32 ]
作者: qzwqzw
时间: 2008-12-12 09:27
大约的情形可以参考下面的帖子
http://www.cn-dos.net/forum/viewthread.php?tid=9452
http://www.cn-dos.net/forum/viewthread.php?tid=20682
目前已知的是
使用Debug必然要启用ntvdm
而它是与cmd差异很大的一种命令行环境
比如命令行自动完成
比如长短文件名
作者: wxcute
时间: 2008-12-12 12:49
还有个问题,这个 choice 不能暂停等待输入(可能就是楼上 qzwqzw 兄说的 "命令行自动完成" 罢),而是一直在 :loop 标签里循环。
作者: wangff
时间: 2008-12-12 14:21
37楼的问题正在确认...
38 楼的问题 应该不存在,是否会沒带参,是哪一搂的程序?
作者: wxcute
时间: 2008-12-12 14:34
标题: 回复 39 楼 wangff
是我没看清,原来 27 楼有带参数暂停的功能。
还有一个问题(环境 XP SP3)
动态检测时如果按了某些键(如 Ctrl)之后就会假死,即再按什么也没有反应了。
快速按几个字母也会出现上述情况。
不知带参执行时会不会?
作者: wangff
时间: 2008-12-12 15:03
"假死"现象会出现,正在找原因...
但应该与debug无关,inc.com也会.
作者: s11ss
时间: 2008-12-13 03:18
写了一段代码,可返回ascii:
>i.com echo h#CX-~AP[hSTX-#pP]3/1/h$CX-}AP[h#JX-V3P]3/1/h'CX-~AP[h$pX-p#P]3/1/h#CX-xAP[h?EX-r#P]3/1/uK
i
echo %errorlevel%
作者: chenall
时间: 2008-12-13 18:24
都系强人,看不懂收藏下备用.
作者: winxos
时间: 2008-12-17 21:53
标题: 好
不过还是借助了汇编。
作者: mmfy
时间: 2009-1-15 19:09
标题: 这是我的一个想法:
@echo off
echo h#CX-~AP[hSTX-#pP]3/1/h$CX-}AP[h#JX-V3P]3/1/h'CX-~AP[h$pX-p#P]3/1/h#CX-xAP[h?EX-r#P]3/1/uK>key.com
chcp 437>nul&graftabl 936>nul
color 2f
:1
cls
echo 请输入密码:%es%
key
set pk=%errorlevel%
set tmp=
if %pk%==13 goto t1
if %pk%==8 goto backspace
if %pk%==97 set tmp=a
if %pk%==98 set tmp=b
if %pk%==99 set tmp=c
if %pk%==100 set tmp=d
if %pk%==101 set tmp=e
if %pk%==102 set tmp=f
if %pk%==103 set tmp=g
if %pk%==104 set tmp=h
if %pk%==105 set tmp=i
if %pk%==106 set tmp=j
if %pk%==107 set tmp=k
if %pk%==108 set tmp=l
if %pk%==109 set tmp=m
if %pk%==110 set tmp=n
if %pk%==111 set tmp=o
if %pk%==112 set tmp=p
if %pk%==113 set tmp=q
if %pk%==114 set tmp=r
if %pk%==115 set tmp=s
if %pk%==116 set tmp=t
if %pk%==117 set tmp=u
if %pk%==118 set tmp=v
if %pk%==119 set tmp=w
if %pk%==120 set tmp=x
if %pk%==121 set tmp=y
if %pk%==122 set tmp=z
if %pk%==48 set tmp=0
if %pk%==49 set tmp=1
if %pk%==50 set tmp=2
if %pk%==51 set tmp=3
if %pk%==52 set tmp=4
if %pk%==53 set tmp=5
if %pk%==54 set tmp=6
if %pk%==55 set tmp=7
if %pk%==56 set tmp=8
if %pk%==59 set tmp=9
if %tmp%== goto 1
set es=%es%*
set ep=%ep%%tmp%
goto 1
:backspace
if "%ep%"=="" goto 1
set ep=%ep:~0,-1%
set es=%es:~0,-1%
goto 1
:t1
echo 你的密码是:%ep%
pause
作者: xiaolongkun0
时间: 2009-4-11 13:48
研究下